From aa706d785ba7a51f271ec7d4988d9c13ef1a4057 Mon Sep 17 00:00:00 2001 From: Zhengbo Li Date: Tue, 10 Jan 2017 17:28:05 -0800 Subject: [PATCH 01/58] Support import fix for missing namespace as well --- src/services/codefixes/importFixes.ts | 1 + .../fourslash/importNameCodeFixNewImportFile3.ts | 15 +++++++++++++++ 2 files changed, 16 insertions(+) create mode 100644 tests/cases/fourslash/importNameCodeFixNewImportFile3.ts diff --git a/src/services/codefixes/importFixes.ts b/src/services/codefixes/importFixes.ts index 3627d60492d..3aefcf994e9 100644 --- a/src/services/codefixes/importFixes.ts +++ b/src/services/codefixes/importFixes.ts @@ -114,6 +114,7 @@ namespace ts.codefix { registerCodeFix({ errorCodes: [ Diagnostics.Cannot_find_name_0.code, + Diagnostics.Cannot_find_namespace_0.code, Diagnostics._0_refers_to_a_UMD_global_but_the_current_file_is_a_module_Consider_adding_an_import_instead.code ], getCodeActions: (context: CodeFixContext) => { diff --git a/tests/cases/fourslash/importNameCodeFixNewImportFile3.ts b/tests/cases/fourslash/importNameCodeFixNewImportFile3.ts new file mode 100644 index 00000000000..af7901e03e6 --- /dev/null +++ b/tests/cases/fourslash/importNameCodeFixNewImportFile3.ts @@ -0,0 +1,15 @@ +/// + +//// [|let t: XXX/*0*/.I;|] + +// @Filename: ./module.ts +//// export module XXX { +//// export interface I { +//// } +//// } + +verify.importFixAtPosition([ +`import { XXX } from "./module"; + +let t: XXX.I;` +]); \ No newline at end of file From 028e4e2b13b4a65d5418865cc22d3b37c935c955 Mon Sep 17 00:00:00 2001 From: Ron Buckton Date: Thu, 26 Jan 2017 15:46:26 -0800 Subject: [PATCH 02/58] Extract printer from emitter for reusability. --- Jakefile.js | 2 + src/compiler/comments.ts | 20 +- src/compiler/declarationEmitter.ts | 16 +- src/compiler/emitter.ts | 2781 +------------------- src/compiler/factory.ts | 13 + src/compiler/printer.ts | 2659 +++++++++++++++++++ src/compiler/sourcemap.ts | 28 +- src/compiler/transformer.ts | 30 +- src/compiler/transformers/es2015.ts | 16 +- src/compiler/transformers/es2017.ts | 16 +- src/compiler/transformers/es5.ts | 18 +- src/compiler/transformers/generators.ts | 6 +- src/compiler/transformers/module/es2015.ts | 16 +- src/compiler/transformers/module/module.ts | 16 +- src/compiler/transformers/module/system.ts | 18 +- src/compiler/transformers/ts.ts | 14 +- src/compiler/tsconfig.json | 1 + src/compiler/types.ts | 75 +- src/compiler/utilities.ts | 42 +- src/harness/tsconfig.json | 1 + src/services/tsconfig.json | 1 + 21 files changed, 2939 insertions(+), 2850 deletions(-) create mode 100644 src/compiler/printer.ts diff --git a/Jakefile.js b/Jakefile.js index 3ee8476c842..a23b9cbe03c 100644 --- a/Jakefile.js +++ b/Jakefile.js @@ -84,6 +84,7 @@ var compilerSources = [ "sourcemap.ts", "comments.ts", "declarationEmitter.ts", + "printer.ts", "emitter.ts", "program.ts", "commandLineParser.ts", @@ -121,6 +122,7 @@ var servicesSources = [ "sourcemap.ts", "comments.ts", "declarationEmitter.ts", + "printer.ts", "emitter.ts", "program.ts", "commandLineParser.ts", diff --git a/src/compiler/comments.ts b/src/compiler/comments.ts index bd9190dbec7..3106d3ccfec 100644 --- a/src/compiler/comments.ts +++ b/src/compiler/comments.ts @@ -5,17 +5,13 @@ namespace ts { export interface CommentWriter { reset(): void; setSourceFile(sourceFile: SourceFile): void; - emitNodeWithComments(emitContext: EmitContext, node: Node, emitCallback: (emitContext: EmitContext, node: Node) => void): void; + emitNodeWithComments(hint: EmitHint, node: Node, emitCallback: (hint: EmitHint, node: Node) => void): void; emitBodyWithDetachedComments(node: Node, detachedRange: TextRange, emitCallback: (node: Node) => void): void; emitTrailingCommentsOfPosition(pos: number): void; } - export function createCommentWriter(host: EmitHost, writer: EmitTextWriter, sourceMap: SourceMapWriter): CommentWriter { - const compilerOptions = host.getCompilerOptions(); + export function createCommentWriter(writer: EmitTextWriter, compilerOptions: CompilerOptions, newLine: string, emitPos: (pos: number) => void): CommentWriter { const extendedDiagnostics = compilerOptions.extendedDiagnostics; - const newLine = host.getNewLine(); - const { emitPos } = sourceMap; - let containerPos = -1; let containerEnd = -1; let declarationListContainerEnd = -1; @@ -34,9 +30,9 @@ namespace ts { emitTrailingCommentsOfPosition, }; - function emitNodeWithComments(emitContext: EmitContext, node: Node, emitCallback: (emitContext: EmitContext, node: Node) => void) { + function emitNodeWithComments(hint: EmitHint, node: Node, emitCallback: (hint: EmitHint, node: Node) => void) { if (disabled) { - emitCallback(emitContext, node); + emitCallback(hint, node); return; } @@ -47,11 +43,11 @@ namespace ts { // Both pos and end are synthesized, so just emit the node without comments. if (emitFlags & EmitFlags.NoNestedComments) { disabled = true; - emitCallback(emitContext, node); + emitCallback(hint, node); disabled = false; } else { - emitCallback(emitContext, node); + emitCallback(hint, node); } } else { @@ -94,11 +90,11 @@ namespace ts { if (emitFlags & EmitFlags.NoNestedComments) { disabled = true; - emitCallback(emitContext, node); + emitCallback(hint, node); disabled = false; } else { - emitCallback(emitContext, node); + emitCallback(hint, node); } if (extendedDiagnostics) { diff --git a/src/compiler/declarationEmitter.ts b/src/compiler/declarationEmitter.ts index 46df4fed689..4b878adaff5 100644 --- a/src/compiler/declarationEmitter.ts +++ b/src/compiler/declarationEmitter.ts @@ -35,13 +35,15 @@ namespace ts { forEachEmittedFile(host, getDeclarationDiagnosticsFromFile, targetSourceFile); return declarationDiagnostics.getDiagnostics(targetSourceFile ? targetSourceFile.fileName : undefined); - function getDeclarationDiagnosticsFromFile({ declarationFilePath }: EmitFileNames, sources: SourceFile[], isBundledEmit: boolean) { - emitDeclarations(host, resolver, declarationDiagnostics, declarationFilePath, sources, isBundledEmit, /*emitOnlyDtsFiles*/ false); + function getDeclarationDiagnosticsFromFile({ declarationFilePath }: EmitFileNames, sourceFileOrBundle: SourceFile | Bundle) { + emitDeclarations(host, resolver, declarationDiagnostics, declarationFilePath, sourceFileOrBundle, /*emitOnlyDtsFiles*/ false); } } function emitDeclarations(host: EmitHost, resolver: EmitResolver, emitterDiagnostics: DiagnosticCollection, declarationFilePath: string, - sourceFiles: SourceFile[], isBundledEmit: boolean, emitOnlyDtsFiles: boolean): DeclarationEmit { + sourceFileOrBundle: SourceFile | Bundle, emitOnlyDtsFiles: boolean): DeclarationEmit { + const sourceFiles = sourceFileOrBundle.kind === SyntaxKind.Bundle ? sourceFileOrBundle.sourceFiles : [sourceFileOrBundle]; + const isBundledEmit = sourceFileOrBundle.kind === SyntaxKind.Bundle; const newLine = host.getNewLine(); const compilerOptions = host.getCompilerOptions(); @@ -1803,8 +1805,9 @@ namespace ts { } return addedBundledEmitReference; - function getDeclFileName(emitFileNames: EmitFileNames, _sourceFiles: SourceFile[], isBundledEmit: boolean) { + function getDeclFileName(emitFileNames: EmitFileNames, sourceFileOrBundle: SourceFile | Bundle) { // Dont add reference path to this file if it is a bundled emit and caller asked not emit bundled file path + const isBundledEmit = sourceFileOrBundle.kind === SyntaxKind.Bundle; if (isBundledEmit && !addBundledFileReference) { return; } @@ -1817,10 +1820,11 @@ namespace ts { } /* @internal */ - export function writeDeclarationFile(declarationFilePath: string, sourceFiles: SourceFile[], isBundledEmit: boolean, host: EmitHost, resolver: EmitResolver, emitterDiagnostics: DiagnosticCollection, emitOnlyDtsFiles: boolean) { - const emitDeclarationResult = emitDeclarations(host, resolver, emitterDiagnostics, declarationFilePath, sourceFiles, isBundledEmit, emitOnlyDtsFiles); + export function writeDeclarationFile(declarationFilePath: string, sourceFileOrBundle: SourceFile | Bundle, host: EmitHost, resolver: EmitResolver, emitterDiagnostics: DiagnosticCollection, emitOnlyDtsFiles: boolean) { + const emitDeclarationResult = emitDeclarations(host, resolver, emitterDiagnostics, declarationFilePath, sourceFileOrBundle, emitOnlyDtsFiles); const emitSkipped = emitDeclarationResult.reportedDeclarationError || host.isEmitBlocked(declarationFilePath) || host.getCompilerOptions().noEmit; if (!emitSkipped) { + const sourceFiles = sourceFileOrBundle.kind === SyntaxKind.Bundle ? sourceFileOrBundle.sourceFiles : [sourceFileOrBundle]; const declarationOutput = emitDeclarationResult.referencesOutput + getDeclarationOutput(emitDeclarationResult.synchronousDeclarationOutput, emitDeclarationResult.moduleElementDeclarationEmitInfo); writeFile(host, emitterDiagnostics, declarationFilePath, declarationOutput, host.getCompilerOptions().emitBOM, sourceFiles); diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index 27285a4c2dc..dd823cf7994 100644 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -1,61 +1,28 @@ -/// +/// /// -/// -/// +/// +/// /// +/// /* @internal */ namespace ts { - // Flags enum to track count of temp variables and a few dedicated names - const enum TempFlags { - Auto = 0x00000000, // No preferred name - CountMask = 0x0FFFFFFF, // Temp variable counter - _i = 0x10000000, // Use/preference flag for '_i' - } - const id = (s: SourceFile) => s; const nullTransformers: Transformer[] = [_ => id]; // targetSourceFile is when users only want one file in entire project to be emitted. This is used in compileOnSave feature export function emitFiles(resolver: EmitResolver, host: EmitHost, targetSourceFile: SourceFile, emitOnlyDtsFiles?: boolean): EmitResult { - const delimiters = createDelimiterMap(); - const brackets = createBracketsMap(); const compilerOptions = host.getCompilerOptions(); - const languageVersion = getEmitScriptTarget(compilerOptions); - const moduleKind = getEmitModuleKind(compilerOptions); const sourceMapDataList: SourceMapData[] = compilerOptions.sourceMap || compilerOptions.inlineSourceMap ? [] : undefined; const emittedFilesList: string[] = compilerOptions.listEmittedFiles ? [] : undefined; const emitterDiagnostics = createDiagnosticCollection(); const newLine = host.getNewLine(); const transformers: Transformer[] = emitOnlyDtsFiles ? nullTransformers : getTransformers(compilerOptions); const writer = createTextWriter(newLine); - const { - write, - writeLine, - increaseIndent, - decreaseIndent - } = writer; - const sourceMap = createSourceMapWriter(host, writer); - const { - emitNodeWithSourceMap, - emitTokenWithSourceMap - } = sourceMap; + const comments = createCommentWriter(writer, compilerOptions, newLine, sourceMap.emitPos); - const comments = createCommentWriter(host, writer, sourceMap); - const { - emitNodeWithComments, - emitBodyWithDetachedComments, - emitTrailingCommentsOfPosition - } = comments; - - let nodeIdToGeneratedName: string[]; - let autoGeneratedIdToGeneratedName: string[]; - let generatedNameSet: Map; - let tempFlags: TempFlags; let currentSourceFile: SourceFile; - let currentText: string; - let currentFileIdentifiers: Map; let bundledHelpers: Map; let isOwnFileEmit: boolean; let emitSkipped = false; @@ -63,17 +30,34 @@ namespace ts { const sourceFiles = getSourceFilesToEmit(host, targetSourceFile); // Transform the source files - performance.mark("beforeTransform"); - const { - transformed, - emitNodeWithSubstitution, - emitNodeWithNotification - } = transformFiles(resolver, host, sourceFiles, transformers); - performance.measure("transformTime", "beforeTransform"); + const transform = transformFiles(resolver, host, sourceFiles, transformers); + + // Create a printer to print the nodes + const printer = createPrinter(writer, compilerOptions, { + // resolver hooks + hasGlobalName: resolver.hasGlobalName, + + // transform hooks + onEmitNode: transform.emitNodeWithNotification, + onSubstituteNode: transform.emitNodeWithSubstitution, + + // sourcemap hooks + onEmitSourceMapOfNode: sourceMap.emitNodeWithSourceMap, + onEmitSourceMapOfToken: sourceMap.emitTokenWithSourceMap, + + // comment hooks + onEmitCommentsOfNode: comments.emitNodeWithComments, + onEmitDetachedCommentsOfNode: comments.emitBodyWithDetachedComments, + onEmitTrailingCommentsOfPosition: comments.emitTrailingCommentsOfPosition, + + // emitter hooks + onEmitHelpers: emitHelpers, + onSetSourceFile: setSourceFile, + }); // Emit each output file performance.mark("beforePrint"); - forEachEmittedFile(host, emitFile, transformed, emitOnlyDtsFiles); + forEachEmittedFile(host, emitSourceFileOrBundle, transform.transformed, emitOnlyDtsFiles); performance.measure("printTime", "beforePrint"); // Clean up emit nodes on parse tree @@ -88,11 +72,11 @@ namespace ts { sourceMaps: sourceMapDataList }; - function emitFile({ jsFilePath, sourceMapFilePath, declarationFilePath }: EmitFileNames, sourceFiles: SourceFile[], isBundledEmit: boolean) { + function emitSourceFileOrBundle({ jsFilePath, sourceMapFilePath, declarationFilePath }: EmitFileNames, sourceFileOrBundle: SourceFile | Bundle) { // Make sure not to write js file and source map file if any of them cannot be written if (!host.isEmitBlocked(jsFilePath) && !compilerOptions.noEmit) { if (!emitOnlyDtsFiles) { - printFile(jsFilePath, sourceMapFilePath, sourceFiles, isBundledEmit); + printSourceFileOrBundle(jsFilePath, sourceMapFilePath, sourceFileOrBundle); } } else { @@ -100,7 +84,7 @@ namespace ts { } if (declarationFilePath) { - emitSkipped = writeDeclarationFile(declarationFilePath, getOriginalSourceFiles(sourceFiles), isBundledEmit, host, resolver, emitterDiagnostics, emitOnlyDtsFiles) || emitSkipped; + emitSkipped = writeDeclarationFile(declarationFilePath, getOriginalSourceFileOrBundle(sourceFileOrBundle), host, resolver, emitterDiagnostics, emitOnlyDtsFiles) || emitSkipped; } if (!emitSkipped && emittedFilesList) { @@ -116,34 +100,32 @@ namespace ts { } } - function printFile(jsFilePath: string, sourceMapFilePath: string, sourceFiles: SourceFile[], isBundledEmit: boolean) { - sourceMap.initialize(jsFilePath, sourceMapFilePath, sourceFiles, isBundledEmit); - nodeIdToGeneratedName = []; - autoGeneratedIdToGeneratedName = []; - generatedNameSet = createMap(); - bundledHelpers = isBundledEmit ? createMap() : undefined; - isOwnFileEmit = !isBundledEmit; + function printSourceFileOrBundle(jsFilePath: string, sourceMapFilePath: string, sourceFileOrBundle: SourceFile | Bundle) { + const bundle = sourceFileOrBundle.kind === SyntaxKind.Bundle ? sourceFileOrBundle : undefined; + const sourceFile = sourceFileOrBundle.kind === SyntaxKind.SourceFile ? sourceFileOrBundle : undefined; + const sourceFiles = bundle ? bundle.sourceFiles : [sourceFile]; + sourceMap.initialize(jsFilePath, sourceMapFilePath, sourceFileOrBundle); - // Emit helpers from all the files - if (isBundledEmit && moduleKind) { - for (const sourceFile of sourceFiles) { - emitHelpers(sourceFile, /*isBundle*/ true); - } + if (bundle) { + bundledHelpers = createMap(); + isOwnFileEmit = false; + printer.printBundle(bundle); + } + else { + isOwnFileEmit = true; + printer.printFile(sourceFile); } - // Print each transformed source file. - forEach(sourceFiles, printSourceFile); - - writeLine(); + writer.writeLine(); const sourceMappingURL = sourceMap.getSourceMappingURL(); if (sourceMappingURL) { - write(`//# ${"sourceMappingURL"}=${sourceMappingURL}`); // Sometimes tools can sometimes see this line as a source mapping url comment + writer.write(`//# ${"sourceMappingURL"}=${sourceMappingURL}`); // Sometimes tools can sometimes see this line as a source mapping url comment } // Write the source map if (compilerOptions.sourceMap && !compilerOptions.inlineSourceMap) { - writeFile(host, emitterDiagnostics, sourceMapFilePath, sourceMap.getText(), /*writeByteOrderMark*/ false, sourceFiles); + writeFile(host, emitterDiagnostics, sourceMapFilePath, sourceMap.getText(), /*writeByteOrderMark*/ false, sourceFiles); } // Record source map data for the test harness. @@ -159,2654 +141,57 @@ namespace ts { comments.reset(); writer.reset(); - tempFlags = TempFlags.Auto; currentSourceFile = undefined; - currentText = undefined; + bundledHelpers = undefined; isOwnFileEmit = false; } - function printSourceFile(node: SourceFile) { + function setSourceFile(node: SourceFile) { currentSourceFile = node; - currentText = node.text; - currentFileIdentifiers = node.identifiers; sourceMap.setSourceFile(node); comments.setSourceFile(node); - pipelineEmitWithNotification(EmitContext.SourceFile, node); } - /** - * Emits a node. - */ - function emit(node: Node) { - pipelineEmitWithNotification(EmitContext.Unspecified, node); - } - - /** - * Emits an IdentifierName. - */ - function emitIdentifierName(node: Identifier) { - pipelineEmitWithNotification(EmitContext.IdentifierName, node); - } - - /** - * Emits an expression node. - */ - function emitExpression(node: Expression) { - pipelineEmitWithNotification(EmitContext.Expression, node); - } - - /** - * Emits a node with possible notification. - * - * NOTE: Do not call this method directly. It is part of the emit pipeline - * and should only be called from printSourceFile, emit, emitExpression, or - * emitIdentifierName. - */ - function pipelineEmitWithNotification(emitContext: EmitContext, node: Node) { - emitNodeWithNotification(emitContext, node, pipelineEmitWithComments); - } - - /** - * Emits a node with comments. - * - * NOTE: Do not call this method directly. It is part of the emit pipeline - * and should only be called indirectly from pipelineEmitWithNotification. - */ - function pipelineEmitWithComments(emitContext: EmitContext, node: Node) { - // Do not emit comments for SourceFile - if (emitContext === EmitContext.SourceFile) { - pipelineEmitWithSourceMap(emitContext, node); - return; - } - - emitNodeWithComments(emitContext, node, pipelineEmitWithSourceMap); - } - - /** - * Emits a node with source maps. - * - * NOTE: Do not call this method directly. It is part of the emit pipeline - * and should only be called indirectly from pipelineEmitWithComments. - */ - function pipelineEmitWithSourceMap(emitContext: EmitContext, node: Node) { - // Do not emit source mappings for SourceFile or IdentifierName - if (emitContext === EmitContext.SourceFile - || emitContext === EmitContext.IdentifierName) { - pipelineEmitWithSubstitution(emitContext, node); - return; - } - - emitNodeWithSourceMap(emitContext, node, pipelineEmitWithSubstitution); - } - - /** - * Emits a node with possible substitution. - * - * NOTE: Do not call this method directly. It is part of the emit pipeline - * and should only be called indirectly from pipelineEmitWithSourceMap or - * pipelineEmitInUnspecifiedContext (when picking a more specific context). - */ - function pipelineEmitWithSubstitution(emitContext: EmitContext, node: Node) { - emitNodeWithSubstitution(emitContext, node, pipelineEmitForContext); - } - - /** - * Emits a node. - * - * NOTE: Do not call this method directly. It is part of the emit pipeline - * and should only be called indirectly from pipelineEmitWithSubstitution. - */ - function pipelineEmitForContext(emitContext: EmitContext, node: Node): void { - switch (emitContext) { - case EmitContext.SourceFile: return pipelineEmitInSourceFileContext(node); - case EmitContext.IdentifierName: return pipelineEmitInIdentifierNameContext(node); - case EmitContext.Unspecified: return pipelineEmitInUnspecifiedContext(node); - case EmitContext.Expression: return pipelineEmitInExpressionContext(node); - } - } - - /** - * Emits a node in the SourceFile EmitContext. - * - * NOTE: Do not call this method directly. It is part of the emit pipeline - * and should only be called indirectly from pipelineEmitForContext. - */ - function pipelineEmitInSourceFileContext(node: Node): void { - const kind = node.kind; - switch (kind) { - // Top-level nodes - case SyntaxKind.SourceFile: - return emitSourceFile(node); - } - } - - /** - * Emits a node in the IdentifierName EmitContext. - * - * NOTE: Do not call this method directly. It is part of the emit pipeline - * and should only be called indirectly from pipelineEmitForContext. - */ - function pipelineEmitInIdentifierNameContext(node: Node): void { - const kind = node.kind; - switch (kind) { - // Identifiers - case SyntaxKind.Identifier: - return emitIdentifier(node); - } - } - - /** - * Emits a node in the Unspecified EmitContext. - * - * NOTE: Do not call this method directly. It is part of the emit pipeline - * and should only be called indirectly from pipelineEmitForContext. - */ - function pipelineEmitInUnspecifiedContext(node: Node): void { - const kind = node.kind; - switch (kind) { - // Pseudo-literals - case SyntaxKind.TemplateHead: - case SyntaxKind.TemplateMiddle: - case SyntaxKind.TemplateTail: - return emitLiteral(node); - - // Identifiers - case SyntaxKind.Identifier: - return emitIdentifier(node); - - // Reserved words - case SyntaxKind.ConstKeyword: - case SyntaxKind.DefaultKeyword: - case SyntaxKind.ExportKeyword: - case SyntaxKind.VoidKeyword: - - // Strict mode reserved words - case SyntaxKind.PrivateKeyword: - case SyntaxKind.ProtectedKeyword: - case SyntaxKind.PublicKeyword: - case SyntaxKind.StaticKeyword: - - // Contextual keywords - case SyntaxKind.AbstractKeyword: - case SyntaxKind.AsKeyword: - case SyntaxKind.AnyKeyword: - case SyntaxKind.AsyncKeyword: - case SyntaxKind.AwaitKeyword: - case SyntaxKind.BooleanKeyword: - case SyntaxKind.ConstructorKeyword: - case SyntaxKind.DeclareKeyword: - case SyntaxKind.GetKeyword: - case SyntaxKind.IsKeyword: - case SyntaxKind.ModuleKeyword: - case SyntaxKind.NamespaceKeyword: - case SyntaxKind.NeverKeyword: - case SyntaxKind.ReadonlyKeyword: - case SyntaxKind.RequireKeyword: - case SyntaxKind.NumberKeyword: - case SyntaxKind.SetKeyword: - case SyntaxKind.StringKeyword: - case SyntaxKind.SymbolKeyword: - case SyntaxKind.TypeKeyword: - case SyntaxKind.UndefinedKeyword: - case SyntaxKind.FromKeyword: - case SyntaxKind.GlobalKeyword: - case SyntaxKind.OfKeyword: - writeTokenText(kind); - return; - - // Parse tree nodes - - // Names - case SyntaxKind.QualifiedName: - return emitQualifiedName(node); - case SyntaxKind.ComputedPropertyName: - return emitComputedPropertyName(node); - - // Signature elements - case SyntaxKind.TypeParameter: - return emitTypeParameter(node); - case SyntaxKind.Parameter: - return emitParameter(node); - case SyntaxKind.Decorator: - return emitDecorator(node); - - // Type members - case SyntaxKind.PropertySignature: - return emitPropertySignature(node); - case SyntaxKind.PropertyDeclaration: - return emitPropertyDeclaration(node); - case SyntaxKind.MethodSignature: - return emitMethodSignature(node); - case SyntaxKind.MethodDeclaration: - return emitMethodDeclaration(node); - case SyntaxKind.Constructor: - return emitConstructor(node); - case SyntaxKind.GetAccessor: - case SyntaxKind.SetAccessor: - return emitAccessorDeclaration(node); - case SyntaxKind.CallSignature: - return emitCallSignature(node); - case SyntaxKind.ConstructSignature: - return emitConstructSignature(node); - case SyntaxKind.IndexSignature: - return emitIndexSignature(node); - - // Types - case SyntaxKind.TypePredicate: - return emitTypePredicate(node); - case SyntaxKind.TypeReference: - return emitTypeReference(node); - case SyntaxKind.FunctionType: - return emitFunctionType(node); - case SyntaxKind.ConstructorType: - return emitConstructorType(node); - case SyntaxKind.TypeQuery: - return emitTypeQuery(node); - case SyntaxKind.TypeLiteral: - return emitTypeLiteral(node); - case SyntaxKind.ArrayType: - return emitArrayType(node); - case SyntaxKind.TupleType: - return emitTupleType(node); - case SyntaxKind.UnionType: - return emitUnionType(node); - case SyntaxKind.IntersectionType: - return emitIntersectionType(node); - case SyntaxKind.ParenthesizedType: - return emitParenthesizedType(node); - case SyntaxKind.ExpressionWithTypeArguments: - return emitExpressionWithTypeArguments(node); - case SyntaxKind.ThisType: - return emitThisType(); - case SyntaxKind.TypeOperator: - return emitTypeOperator(node); - case SyntaxKind.IndexedAccessType: - return emitIndexedAccessType(node); - case SyntaxKind.MappedType: - return emitMappedType(node); - case SyntaxKind.LiteralType: - return emitLiteralType(node); - - // Binding patterns - case SyntaxKind.ObjectBindingPattern: - return emitObjectBindingPattern(node); - case SyntaxKind.ArrayBindingPattern: - return emitArrayBindingPattern(node); - case SyntaxKind.BindingElement: - return emitBindingElement(node); - - // Misc - case SyntaxKind.TemplateSpan: - return emitTemplateSpan(node); - case SyntaxKind.SemicolonClassElement: - return emitSemicolonClassElement(); - - // Statements - case SyntaxKind.Block: - return emitBlock(node); - case SyntaxKind.VariableStatement: - return emitVariableStatement(node); - case SyntaxKind.EmptyStatement: - return emitEmptyStatement(); - case SyntaxKind.ExpressionStatement: - return emitExpressionStatement(node); - case SyntaxKind.IfStatement: - return emitIfStatement(node); - case SyntaxKind.DoStatement: - return emitDoStatement(node); - case SyntaxKind.WhileStatement: - return emitWhileStatement(node); - case SyntaxKind.ForStatement: - return emitForStatement(node); - case SyntaxKind.ForInStatement: - return emitForInStatement(node); - case SyntaxKind.ForOfStatement: - return emitForOfStatement(node); - case SyntaxKind.ContinueStatement: - return emitContinueStatement(node); - case SyntaxKind.BreakStatement: - return emitBreakStatement(node); - case SyntaxKind.ReturnStatement: - return emitReturnStatement(node); - case SyntaxKind.WithStatement: - return emitWithStatement(node); - case SyntaxKind.SwitchStatement: - return emitSwitchStatement(node); - case SyntaxKind.LabeledStatement: - return emitLabeledStatement(node); - case SyntaxKind.ThrowStatement: - return emitThrowStatement(node); - case SyntaxKind.TryStatement: - return emitTryStatement(node); - case SyntaxKind.DebuggerStatement: - return emitDebuggerStatement(node); - - // Declarations - case SyntaxKind.VariableDeclaration: - return emitVariableDeclaration(node); - case SyntaxKind.VariableDeclarationList: - return emitVariableDeclarationList(node); - case SyntaxKind.FunctionDeclaration: - return emitFunctionDeclaration(node); - case SyntaxKind.ClassDeclaration: - return emitClassDeclaration(node); - case SyntaxKind.InterfaceDeclaration: - return emitInterfaceDeclaration(node); - case SyntaxKind.TypeAliasDeclaration: - return emitTypeAliasDeclaration(node); - case SyntaxKind.EnumDeclaration: - return emitEnumDeclaration(node); - case SyntaxKind.ModuleDeclaration: - return emitModuleDeclaration(node); - case SyntaxKind.ModuleBlock: - return emitModuleBlock(node); - case SyntaxKind.CaseBlock: - return emitCaseBlock(node); - case SyntaxKind.ImportEqualsDeclaration: - return emitImportEqualsDeclaration(node); - case SyntaxKind.ImportDeclaration: - return emitImportDeclaration(node); - case SyntaxKind.ImportClause: - return emitImportClause(node); - case SyntaxKind.NamespaceImport: - return emitNamespaceImport(node); - case SyntaxKind.NamedImports: - return emitNamedImports(node); - case SyntaxKind.ImportSpecifier: - return emitImportSpecifier(node); - case SyntaxKind.ExportAssignment: - return emitExportAssignment(node); - case SyntaxKind.ExportDeclaration: - return emitExportDeclaration(node); - case SyntaxKind.NamedExports: - return emitNamedExports(node); - case SyntaxKind.ExportSpecifier: - return emitExportSpecifier(node); - case SyntaxKind.MissingDeclaration: - return; - - // Module references - case SyntaxKind.ExternalModuleReference: - return emitExternalModuleReference(node); - - // JSX (non-expression) - case SyntaxKind.JsxText: - return emitJsxText(node); - case SyntaxKind.JsxOpeningElement: - return emitJsxOpeningElement(node); - case SyntaxKind.JsxClosingElement: - return emitJsxClosingElement(node); - case SyntaxKind.JsxAttribute: - return emitJsxAttribute(node); - case SyntaxKind.JsxSpreadAttribute: - return emitJsxSpreadAttribute(node); - case SyntaxKind.JsxExpression: - return emitJsxExpression(node); - - // Clauses - case SyntaxKind.CaseClause: - return emitCaseClause(node); - case SyntaxKind.DefaultClause: - return emitDefaultClause(node); - case SyntaxKind.HeritageClause: - return emitHeritageClause(node); - case SyntaxKind.CatchClause: - return emitCatchClause(node); - - // Property assignments - case SyntaxKind.PropertyAssignment: - return emitPropertyAssignment(node); - case SyntaxKind.ShorthandPropertyAssignment: - return emitShorthandPropertyAssignment(node); - case SyntaxKind.SpreadAssignment: - return emitSpreadAssignment(node as SpreadAssignment); - - // Enum - case SyntaxKind.EnumMember: - return emitEnumMember(node); - - // JSDoc nodes (ignored) - // Transformation nodes (ignored) - } - - // If the node is an expression, try to emit it as an expression with - // substitution. - if (isExpression(node)) { - return pipelineEmitWithSubstitution(EmitContext.Expression, node); - } - } - - /** - * Emits a node in the Expression EmitContext. - * - * NOTE: Do not call this method directly. It is part of the emit pipeline - * and should only be called indirectly from pipelineEmitForContext. - */ - function pipelineEmitInExpressionContext(node: Node): void { - const kind = node.kind; - switch (kind) { - // Literals - case SyntaxKind.NumericLiteral: - return emitNumericLiteral(node); - - case SyntaxKind.StringLiteral: - case SyntaxKind.RegularExpressionLiteral: - case SyntaxKind.NoSubstitutionTemplateLiteral: - return emitLiteral(node); - - // Identifiers - case SyntaxKind.Identifier: - return emitIdentifier(node); - - // Reserved words - case SyntaxKind.FalseKeyword: - case SyntaxKind.NullKeyword: - case SyntaxKind.SuperKeyword: - case SyntaxKind.TrueKeyword: - case SyntaxKind.ThisKeyword: - writeTokenText(kind); - return; - - // Expressions - case SyntaxKind.ArrayLiteralExpression: - return emitArrayLiteralExpression(node); - case SyntaxKind.ObjectLiteralExpression: - return emitObjectLiteralExpression(node); - case SyntaxKind.PropertyAccessExpression: - return emitPropertyAccessExpression(node); - case SyntaxKind.ElementAccessExpression: - return emitElementAccessExpression(node); - case SyntaxKind.CallExpression: - return emitCallExpression(node); - case SyntaxKind.NewExpression: - return emitNewExpression(node); - case SyntaxKind.TaggedTemplateExpression: - return emitTaggedTemplateExpression(node); - case SyntaxKind.TypeAssertionExpression: - return emitTypeAssertionExpression(node); - case SyntaxKind.ParenthesizedExpression: - return emitParenthesizedExpression(node); - case SyntaxKind.FunctionExpression: - return emitFunctionExpression(node); - case SyntaxKind.ArrowFunction: - return emitArrowFunction(node); - case SyntaxKind.DeleteExpression: - return emitDeleteExpression(node); - case SyntaxKind.TypeOfExpression: - return emitTypeOfExpression(node); - case SyntaxKind.VoidExpression: - return emitVoidExpression(node); - case SyntaxKind.AwaitExpression: - return emitAwaitExpression(node); - case SyntaxKind.PrefixUnaryExpression: - return emitPrefixUnaryExpression(node); - case SyntaxKind.PostfixUnaryExpression: - return emitPostfixUnaryExpression(node); - case SyntaxKind.BinaryExpression: - return emitBinaryExpression(node); - case SyntaxKind.ConditionalExpression: - return emitConditionalExpression(node); - case SyntaxKind.TemplateExpression: - return emitTemplateExpression(node); - case SyntaxKind.YieldExpression: - return emitYieldExpression(node); - case SyntaxKind.SpreadElement: - return emitSpreadExpression(node); - case SyntaxKind.ClassExpression: - return emitClassExpression(node); - case SyntaxKind.OmittedExpression: - return; - case SyntaxKind.AsExpression: - return emitAsExpression(node); - case SyntaxKind.NonNullExpression: - return emitNonNullExpression(node); - case SyntaxKind.MetaProperty: - return emitMetaProperty(node); - - // JSX - case SyntaxKind.JsxElement: - return emitJsxElement(node); - case SyntaxKind.JsxSelfClosingElement: - return emitJsxSelfClosingElement(node); - - // Transformation nodes - case SyntaxKind.PartiallyEmittedExpression: - return emitPartiallyEmittedExpression(node); - } - } - - // - // Literals/Pseudo-literals - // - - // SyntaxKind.NumericLiteral - function emitNumericLiteral(node: NumericLiteral) { - emitLiteral(node); - if (node.trailingComment) { - write(` /*${node.trailingComment}*/`); - } - } - - // SyntaxKind.StringLiteral - // SyntaxKind.RegularExpressionLiteral - // SyntaxKind.NoSubstitutionTemplateLiteral - // SyntaxKind.TemplateHead - // SyntaxKind.TemplateMiddle - // SyntaxKind.TemplateTail - function emitLiteral(node: LiteralLikeNode) { - const text = getLiteralTextOfNode(node); - if ((compilerOptions.sourceMap || compilerOptions.inlineSourceMap) - && (node.kind === SyntaxKind.StringLiteral || isTemplateLiteralKind(node.kind))) { - writer.writeLiteral(text); - } - else { - write(text); - } - } - - // - // Identifiers - // - - function emitIdentifier(node: Identifier) { - write(getTextOfNode(node, /*includeTrivia*/ false)); - } - - // - // Names - // - - function emitQualifiedName(node: QualifiedName) { - emitEntityName(node.left); - write("."); - emit(node.right); - } - - function emitEntityName(node: EntityName) { - if (node.kind === SyntaxKind.Identifier) { - emitExpression(node); - } - else { - emit(node); - } - } - - function emitComputedPropertyName(node: ComputedPropertyName) { - write("["); - emitExpression(node.expression); - write("]"); - } - - // - // Signature elements - // - - function emitTypeParameter(node: TypeParameterDeclaration) { - emit(node.name); - emitWithPrefix(" extends ", node.constraint); - } - - function emitParameter(node: ParameterDeclaration) { - emitDecorators(node, node.decorators); - emitModifiers(node, node.modifiers); - writeIfPresent(node.dotDotDotToken, "..."); - emit(node.name); - writeIfPresent(node.questionToken, "?"); - emitExpressionWithPrefix(" = ", node.initializer); - emitWithPrefix(": ", node.type); - } - - function emitDecorator(decorator: Decorator) { - write("@"); - emitExpression(decorator.expression); - } - - // - // Type members - // - - function emitPropertySignature(node: PropertySignature) { - emitDecorators(node, node.decorators); - emitModifiers(node, node.modifiers); - emit(node.name); - writeIfPresent(node.questionToken, "?"); - emitWithPrefix(": ", node.type); - write(";"); - } - - function emitPropertyDeclaration(node: PropertyDeclaration) { - emitDecorators(node, node.decorators); - emitModifiers(node, node.modifiers); - emit(node.name); - emitWithPrefix(": ", node.type); - emitExpressionWithPrefix(" = ", node.initializer); - write(";"); - } - - function emitMethodSignature(node: MethodSignature) { - emitDecorators(node, node.decorators); - emitModifiers(node, node.modifiers); - emit(node.name); - writeIfPresent(node.questionToken, "?"); - emitTypeParameters(node, node.typeParameters); - emitParameters(node, node.parameters); - emitWithPrefix(": ", node.type); - write(";"); - } - - function emitMethodDeclaration(node: MethodDeclaration) { - emitDecorators(node, node.decorators); - emitModifiers(node, node.modifiers); - writeIfPresent(node.asteriskToken, "*"); - emit(node.name); - emitSignatureAndBody(node, emitSignatureHead); - } - - function emitConstructor(node: ConstructorDeclaration) { - emitModifiers(node, node.modifiers); - write("constructor"); - emitSignatureAndBody(node, emitSignatureHead); - } - - function emitAccessorDeclaration(node: AccessorDeclaration) { - emitDecorators(node, node.decorators); - emitModifiers(node, node.modifiers); - write(node.kind === SyntaxKind.GetAccessor ? "get " : "set "); - emit(node.name); - emitSignatureAndBody(node, emitSignatureHead); - } - - function emitCallSignature(node: CallSignatureDeclaration) { - emitDecorators(node, node.decorators); - emitModifiers(node, node.modifiers); - emitTypeParameters(node, node.typeParameters); - emitParameters(node, node.parameters); - emitWithPrefix(": ", node.type); - write(";"); - } - - function emitConstructSignature(node: ConstructSignatureDeclaration) { - emitDecorators(node, node.decorators); - emitModifiers(node, node.modifiers); - write("new "); - emitTypeParameters(node, node.typeParameters); - emitParameters(node, node.parameters); - emitWithPrefix(": ", node.type); - write(";"); - } - - function emitIndexSignature(node: IndexSignatureDeclaration) { - emitDecorators(node, node.decorators); - emitModifiers(node, node.modifiers); - emitParametersForIndexSignature(node, node.parameters); - emitWithPrefix(": ", node.type); - write(";"); - } - - function emitSemicolonClassElement() { - write(";"); - } - - // - // Types - // - - function emitTypePredicate(node: TypePredicateNode) { - emit(node.parameterName); - write(" is "); - emit(node.type); - } - - function emitTypeReference(node: TypeReferenceNode) { - emit(node.typeName); - emitTypeArguments(node, node.typeArguments); - } - - function emitFunctionType(node: FunctionTypeNode) { - emitTypeParameters(node, node.typeParameters); - emitParametersForArrow(node, node.parameters); - write(" => "); - emit(node.type); - } - - function emitConstructorType(node: ConstructorTypeNode) { - write("new "); - emitTypeParameters(node, node.typeParameters); - emitParametersForArrow(node, node.parameters); - write(" => "); - emit(node.type); - } - - function emitTypeQuery(node: TypeQueryNode) { - write("typeof "); - emit(node.exprName); - } - - function emitTypeLiteral(node: TypeLiteralNode) { - write("{"); - emitList(node, node.members, ListFormat.TypeLiteralMembers); - write("}"); - } - - function emitArrayType(node: ArrayTypeNode) { - emit(node.elementType); - write("[]"); - } - - function emitTupleType(node: TupleTypeNode) { - write("["); - emitList(node, node.elementTypes, ListFormat.TupleTypeElements); - write("]"); - } - - function emitUnionType(node: UnionTypeNode) { - emitList(node, node.types, ListFormat.UnionTypeConstituents); - } - - function emitIntersectionType(node: IntersectionTypeNode) { - emitList(node, node.types, ListFormat.IntersectionTypeConstituents); - } - - function emitParenthesizedType(node: ParenthesizedTypeNode) { - write("("); - emit(node.type); - write(")"); - } - - function emitThisType() { - write("this"); - } - - function emitTypeOperator(node: TypeOperatorNode) { - writeTokenText(node.operator); - write(" "); - emit(node.type); - } - - function emitIndexedAccessType(node: IndexedAccessTypeNode) { - emit(node.objectType); - write("["); - emit(node.indexType); - write("]"); - } - - function emitMappedType(node: MappedTypeNode) { - write("{"); - writeLine(); - increaseIndent(); - if (node.readonlyToken) { - write("readonly "); - } - write("["); - emit(node.typeParameter.name); - write(" in "); - emit(node.typeParameter.constraint); - write("]"); - if (node.questionToken) { - write("?"); - } - write(": "); - emit(node.type); - write(";"); - writeLine(); - decreaseIndent(); - write("}"); - } - - function emitLiteralType(node: LiteralTypeNode) { - emitExpression(node.literal); - } - - // - // Binding patterns - // - - function emitObjectBindingPattern(node: ObjectBindingPattern) { - const elements = node.elements; - if (elements.length === 0) { - write("{}"); - } - else { - write("{"); - emitList(node, elements, ListFormat.ObjectBindingPatternElements); - write("}"); - } - } - - function emitArrayBindingPattern(node: ArrayBindingPattern) { - const elements = node.elements; - if (elements.length === 0) { - write("[]"); - } - else { - write("["); - emitList(node, node.elements, ListFormat.ArrayBindingPatternElements); - write("]"); - } - } - - function emitBindingElement(node: BindingElement) { - emitWithSuffix(node.propertyName, ": "); - writeIfPresent(node.dotDotDotToken, "..."); - emit(node.name); - emitExpressionWithPrefix(" = ", node.initializer); - } - - // - // Expressions - // - - function emitArrayLiteralExpression(node: ArrayLiteralExpression) { - const elements = node.elements; - if (elements.length === 0) { - write("[]"); - } - else { - const preferNewLine = node.multiLine ? ListFormat.PreferNewLine : ListFormat.None; - emitExpressionList(node, elements, ListFormat.ArrayLiteralExpressionElements | preferNewLine); - } - } - - function emitObjectLiteralExpression(node: ObjectLiteralExpression) { - const properties = node.properties; - if (properties.length === 0) { - write("{}"); - } - else { - const indentedFlag = getEmitFlags(node) & EmitFlags.Indented; - if (indentedFlag) { - increaseIndent(); - } - - const preferNewLine = node.multiLine ? ListFormat.PreferNewLine : ListFormat.None; - const allowTrailingComma = languageVersion >= ScriptTarget.ES5 ? ListFormat.AllowTrailingComma : ListFormat.None; - emitList(node, properties, ListFormat.ObjectLiteralExpressionProperties | allowTrailingComma | preferNewLine); - - if (indentedFlag) { - decreaseIndent(); - } - } - } - - function emitPropertyAccessExpression(node: PropertyAccessExpression) { - let indentBeforeDot = false; - let indentAfterDot = false; - if (!(getEmitFlags(node) & EmitFlags.NoIndentation)) { - const dotRangeStart = node.expression.end; - const dotRangeEnd = skipTrivia(currentText, node.expression.end) + 1; - const dotToken = { kind: SyntaxKind.DotToken, pos: dotRangeStart, end: dotRangeEnd }; - indentBeforeDot = needsIndentation(node, node.expression, dotToken); - indentAfterDot = needsIndentation(node, dotToken, node.name); - } - - emitExpression(node.expression); - increaseIndentIf(indentBeforeDot); - - const shouldEmitDotDot = !indentBeforeDot && needsDotDotForPropertyAccess(node.expression); - write(shouldEmitDotDot ? ".." : "."); - - increaseIndentIf(indentAfterDot); - emit(node.name); - decreaseIndentIf(indentBeforeDot, indentAfterDot); - } - - // 1..toString is a valid property access, emit a dot after the literal - // Also emit a dot if expression is a integer const enum value - it will appear in generated code as numeric literal - function needsDotDotForPropertyAccess(expression: Expression) { - if (expression.kind === SyntaxKind.NumericLiteral) { - // check if numeric literal is a decimal literal that was originally written with a dot - const text = getLiteralTextOfNode(expression); - return getNumericLiteralFlags(text, /*hint*/ NumericLiteralFlags.All) === NumericLiteralFlags.None - && !(expression).isOctalLiteral - && text.indexOf(tokenToString(SyntaxKind.DotToken)) < 0; - } - else if (isPropertyAccessExpression(expression) || isElementAccessExpression(expression)) { - // check if constant enum value is integer - const constantValue = getConstantValue(expression); - // isFinite handles cases when constantValue is undefined - return isFinite(constantValue) - && Math.floor(constantValue) === constantValue - && compilerOptions.removeComments; - } - } - - function emitElementAccessExpression(node: ElementAccessExpression) { - emitExpression(node.expression); - write("["); - emitExpression(node.argumentExpression); - write("]"); - } - - function emitCallExpression(node: CallExpression) { - emitExpression(node.expression); - emitTypeArguments(node, node.typeArguments); - emitExpressionList(node, node.arguments, ListFormat.CallExpressionArguments); - } - - function emitNewExpression(node: NewExpression) { - write("new "); - emitExpression(node.expression); - emitTypeArguments(node, node.typeArguments); - emitExpressionList(node, node.arguments, ListFormat.NewExpressionArguments); - } - - function emitTaggedTemplateExpression(node: TaggedTemplateExpression) { - emitExpression(node.tag); - write(" "); - emitExpression(node.template); - } - - function emitTypeAssertionExpression(node: TypeAssertion) { - if (node.type) { - write("<"); - emit(node.type); - write(">"); - } - - emitExpression(node.expression); - } - - function emitParenthesizedExpression(node: ParenthesizedExpression) { - write("("); - emitExpression(node.expression); - write(")"); - } - - function emitFunctionExpression(node: FunctionExpression) { - emitFunctionDeclarationOrExpression(node); - } - - function emitArrowFunction(node: ArrowFunction) { - emitDecorators(node, node.decorators); - emitModifiers(node, node.modifiers); - emitSignatureAndBody(node, emitArrowFunctionHead); - } - - function emitArrowFunctionHead(node: ArrowFunction) { - emitTypeParameters(node, node.typeParameters); - emitParametersForArrow(node, node.parameters); - emitWithPrefix(": ", node.type); - write(" =>"); - } - - function emitDeleteExpression(node: DeleteExpression) { - write("delete "); - emitExpression(node.expression); - } - - function emitTypeOfExpression(node: TypeOfExpression) { - write("typeof "); - emitExpression(node.expression); - } - - function emitVoidExpression(node: VoidExpression) { - write("void "); - emitExpression(node.expression); - } - - function emitAwaitExpression(node: AwaitExpression) { - write("await "); - emitExpression(node.expression); - } - - function emitPrefixUnaryExpression(node: PrefixUnaryExpression) { - writeTokenText(node.operator); - if (shouldEmitWhitespaceBeforeOperand(node)) { - write(" "); - } - emitExpression(node.operand); - } - - function shouldEmitWhitespaceBeforeOperand(node: PrefixUnaryExpression) { - // In some cases, we need to emit a space between the operator and the operand. One obvious case - // is when the operator is an identifier, like delete or typeof. We also need to do this for plus - // and minus expressions in certain cases. Specifically, consider the following two cases (parens - // are just for clarity of exposition, and not part of the source code): - // - // (+(+1)) - // (+(++1)) - // - // We need to emit a space in both cases. In the first case, the absence of a space will make - // the resulting expression a prefix increment operation. And in the second, it will make the resulting - // expression a prefix increment whose operand is a plus expression - (++(+x)) - // The same is true of minus of course. - const operand = node.operand; - return operand.kind === SyntaxKind.PrefixUnaryExpression - && ((node.operator === SyntaxKind.PlusToken && ((operand).operator === SyntaxKind.PlusToken || (operand).operator === SyntaxKind.PlusPlusToken)) - || (node.operator === SyntaxKind.MinusToken && ((operand).operator === SyntaxKind.MinusToken || (operand).operator === SyntaxKind.MinusMinusToken))); - } - - function emitPostfixUnaryExpression(node: PostfixUnaryExpression) { - emitExpression(node.operand); - writeTokenText(node.operator); - } - - function emitBinaryExpression(node: BinaryExpression) { - const isCommaOperator = node.operatorToken.kind !== SyntaxKind.CommaToken; - const indentBeforeOperator = needsIndentation(node, node.left, node.operatorToken); - const indentAfterOperator = needsIndentation(node, node.operatorToken, node.right); - - emitExpression(node.left); - increaseIndentIf(indentBeforeOperator, isCommaOperator ? " " : undefined); - writeTokenText(node.operatorToken.kind); - increaseIndentIf(indentAfterOperator, " "); - emitExpression(node.right); - decreaseIndentIf(indentBeforeOperator, indentAfterOperator); - } - - function emitConditionalExpression(node: ConditionalExpression) { - const indentBeforeQuestion = needsIndentation(node, node.condition, node.questionToken); - const indentAfterQuestion = needsIndentation(node, node.questionToken, node.whenTrue); - const indentBeforeColon = needsIndentation(node, node.whenTrue, node.colonToken); - const indentAfterColon = needsIndentation(node, node.colonToken, node.whenFalse); - - emitExpression(node.condition); - increaseIndentIf(indentBeforeQuestion, " "); - write("?"); - increaseIndentIf(indentAfterQuestion, " "); - emitExpression(node.whenTrue); - decreaseIndentIf(indentBeforeQuestion, indentAfterQuestion); - - increaseIndentIf(indentBeforeColon, " "); - write(":"); - increaseIndentIf(indentAfterColon, " "); - emitExpression(node.whenFalse); - decreaseIndentIf(indentBeforeColon, indentAfterColon); - } - - function emitTemplateExpression(node: TemplateExpression) { - emit(node.head); - emitList(node, node.templateSpans, ListFormat.TemplateExpressionSpans); - } - - function emitYieldExpression(node: YieldExpression) { - write(node.asteriskToken ? "yield*" : "yield"); - emitExpressionWithPrefix(" ", node.expression); - } - - function emitSpreadExpression(node: SpreadElement) { - write("..."); - emitExpression(node.expression); - } - - function emitClassExpression(node: ClassExpression) { - emitClassDeclarationOrExpression(node); - } - - function emitExpressionWithTypeArguments(node: ExpressionWithTypeArguments) { - emitExpression(node.expression); - emitTypeArguments(node, node.typeArguments); - } - - function emitAsExpression(node: AsExpression) { - emitExpression(node.expression); - if (node.type) { - write(" as "); - emit(node.type); - } - } - - function emitNonNullExpression(node: NonNullExpression) { - emitExpression(node.expression); - write("!"); - } - - function emitMetaProperty(node: MetaProperty) { - writeToken(node.keywordToken, node.pos); - write("."); - emit(node.name); - } - - // - // Misc - // - - function emitTemplateSpan(node: TemplateSpan) { - emitExpression(node.expression); - emit(node.literal); - } - - // - // Statements - // - - function emitBlock(node: Block) { - if (isSingleLineEmptyBlock(node)) { - writeToken(SyntaxKind.OpenBraceToken, node.pos, /*contextNode*/ node); - write(" "); - writeToken(SyntaxKind.CloseBraceToken, node.statements.end, /*contextNode*/ node); - } - else { - writeToken(SyntaxKind.OpenBraceToken, node.pos, /*contextNode*/ node); - emitBlockStatements(node); - writeToken(SyntaxKind.CloseBraceToken, node.statements.end, /*contextNode*/ node); - } - } - - function emitBlockStatements(node: BlockLike) { - if (getEmitFlags(node) & EmitFlags.SingleLine) { - emitList(node, node.statements, ListFormat.SingleLineBlockStatements); - } - else { - emitList(node, node.statements, ListFormat.MultiLineBlockStatements); - } - } - - function emitVariableStatement(node: VariableStatement) { - emitModifiers(node, node.modifiers); - emit(node.declarationList); - write(";"); - } - - function emitEmptyStatement() { - write(";"); - } - - function emitExpressionStatement(node: ExpressionStatement) { - emitExpression(node.expression); - write(";"); - } - - function emitIfStatement(node: IfStatement) { - const openParenPos = writeToken(SyntaxKind.IfKeyword, node.pos, node); - write(" "); - writeToken(SyntaxKind.OpenParenToken, openParenPos, node); - emitExpression(node.expression); - writeToken(SyntaxKind.CloseParenToken, node.expression.end, node); - emitEmbeddedStatement(node, node.thenStatement); - if (node.elseStatement) { - writeLineOrSpace(node); - writeToken(SyntaxKind.ElseKeyword, node.thenStatement.end, node); - if (node.elseStatement.kind === SyntaxKind.IfStatement) { - write(" "); - emit(node.elseStatement); - } - else { - emitEmbeddedStatement(node, node.elseStatement); - } - } - } - - function emitDoStatement(node: DoStatement) { - write("do"); - emitEmbeddedStatement(node, node.statement); - if (isBlock(node.statement)) { - write(" "); - } - else { - writeLineOrSpace(node); - } - - write("while ("); - emitExpression(node.expression); - write(");"); - } - - function emitWhileStatement(node: WhileStatement) { - write("while ("); - emitExpression(node.expression); - write(")"); - emitEmbeddedStatement(node, node.statement); - } - - function emitForStatement(node: ForStatement) { - const openParenPos = writeToken(SyntaxKind.ForKeyword, node.pos); - write(" "); - writeToken(SyntaxKind.OpenParenToken, openParenPos, /*contextNode*/ node); - emitForBinding(node.initializer); - write(";"); - emitExpressionWithPrefix(" ", node.condition); - write(";"); - emitExpressionWithPrefix(" ", node.incrementor); - write(")"); - emitEmbeddedStatement(node, node.statement); - } - - function emitForInStatement(node: ForInStatement) { - const openParenPos = writeToken(SyntaxKind.ForKeyword, node.pos); - write(" "); - writeToken(SyntaxKind.OpenParenToken, openParenPos); - emitForBinding(node.initializer); - write(" in "); - emitExpression(node.expression); - writeToken(SyntaxKind.CloseParenToken, node.expression.end); - emitEmbeddedStatement(node, node.statement); - } - - function emitForOfStatement(node: ForOfStatement) { - const openParenPos = writeToken(SyntaxKind.ForKeyword, node.pos); - write(" "); - writeToken(SyntaxKind.OpenParenToken, openParenPos); - emitForBinding(node.initializer); - write(" of "); - emitExpression(node.expression); - writeToken(SyntaxKind.CloseParenToken, node.expression.end); - emitEmbeddedStatement(node, node.statement); - } - - function emitForBinding(node: VariableDeclarationList | Expression) { - if (node !== undefined) { - if (node.kind === SyntaxKind.VariableDeclarationList) { - emit(node); - } - else { - emitExpression(node); - } - } - } - - function emitContinueStatement(node: ContinueStatement) { - writeToken(SyntaxKind.ContinueKeyword, node.pos); - emitWithPrefix(" ", node.label); - write(";"); - } - - function emitBreakStatement(node: BreakStatement) { - writeToken(SyntaxKind.BreakKeyword, node.pos); - emitWithPrefix(" ", node.label); - write(";"); - } - - function emitReturnStatement(node: ReturnStatement) { - writeToken(SyntaxKind.ReturnKeyword, node.pos, /*contextNode*/ node); - emitExpressionWithPrefix(" ", node.expression); - write(";"); - } - - function emitWithStatement(node: WithStatement) { - write("with ("); - emitExpression(node.expression); - write(")"); - emitEmbeddedStatement(node, node.statement); - } - - function emitSwitchStatement(node: SwitchStatement) { - const openParenPos = writeToken(SyntaxKind.SwitchKeyword, node.pos); - write(" "); - writeToken(SyntaxKind.OpenParenToken, openParenPos); - emitExpression(node.expression); - writeToken(SyntaxKind.CloseParenToken, node.expression.end); - write(" "); - emit(node.caseBlock); - } - - function emitLabeledStatement(node: LabeledStatement) { - emit(node.label); - write(": "); - emit(node.statement); - } - - function emitThrowStatement(node: ThrowStatement) { - write("throw"); - emitExpressionWithPrefix(" ", node.expression); - write(";"); - } - - function emitTryStatement(node: TryStatement) { - write("try "); - emit(node.tryBlock); - if (node.catchClause) { - writeLineOrSpace(node); - emit(node.catchClause); - } - if (node.finallyBlock) { - writeLineOrSpace(node); - write("finally "); - emit(node.finallyBlock); - } - } - - function emitDebuggerStatement(node: DebuggerStatement) { - writeToken(SyntaxKind.DebuggerKeyword, node.pos); - write(";"); - } - - // - // Declarations - // - - function emitVariableDeclaration(node: VariableDeclaration) { - emit(node.name); - emitWithPrefix(": ", node.type); - emitExpressionWithPrefix(" = ", node.initializer); - } - - function emitVariableDeclarationList(node: VariableDeclarationList) { - write(isLet(node) ? "let " : isConst(node) ? "const " : "var "); - emitList(node, node.declarations, ListFormat.VariableDeclarationList); - } - - function emitFunctionDeclaration(node: FunctionDeclaration) { - emitFunctionDeclarationOrExpression(node); - } - - function emitFunctionDeclarationOrExpression(node: FunctionDeclaration | FunctionExpression) { - emitDecorators(node, node.decorators); - emitModifiers(node, node.modifiers); - write(node.asteriskToken ? "function* " : "function "); - emitIdentifierName(node.name); - emitSignatureAndBody(node, emitSignatureHead); - } - - function emitSignatureAndBody(node: FunctionLikeDeclaration, emitSignatureHead: (node: SignatureDeclaration) => void) { - const body = node.body; - if (body) { - if (isBlock(body)) { - const indentedFlag = getEmitFlags(node) & EmitFlags.Indented; - if (indentedFlag) { - increaseIndent(); - } - - if (getEmitFlags(node) & EmitFlags.ReuseTempVariableScope) { - emitSignatureHead(node); - emitBlockFunctionBody(body); - } - else { - const savedTempFlags = tempFlags; - tempFlags = 0; - emitSignatureHead(node); - emitBlockFunctionBody(body); - tempFlags = savedTempFlags; - } - - if (indentedFlag) { - decreaseIndent(); - } - } - else { - emitSignatureHead(node); - write(" "); - emitExpression(body); - } - } - else { - emitSignatureHead(node); - write(";"); - } - - } - - function emitSignatureHead(node: FunctionDeclaration | FunctionExpression | MethodDeclaration | AccessorDeclaration | ConstructorDeclaration) { - emitTypeParameters(node, node.typeParameters); - emitParameters(node, node.parameters); - emitWithPrefix(": ", node.type); - } - - function shouldEmitBlockFunctionBodyOnSingleLine(body: Block) { - // We must emit a function body as a single-line body in the following case: - // * The body has NodeEmitFlags.SingleLine specified. - - // We must emit a function body as a multi-line body in the following cases: - // * The body is explicitly marked as multi-line. - // * A non-synthesized body's start and end position are on different lines. - // * Any statement in the body starts on a new line. - - if (getEmitFlags(body) & EmitFlags.SingleLine) { - return true; - } - - if (body.multiLine) { - return false; - } - - if (!nodeIsSynthesized(body) && !rangeIsOnSingleLine(body, currentSourceFile)) { - return false; - } - - if (shouldWriteLeadingLineTerminator(body, body.statements, ListFormat.PreserveLines) - || shouldWriteClosingLineTerminator(body, body.statements, ListFormat.PreserveLines)) { - return false; - } - - let previousStatement: Statement; - for (const statement of body.statements) { - if (shouldWriteSeparatingLineTerminator(previousStatement, statement, ListFormat.PreserveLines)) { - return false; - } - - previousStatement = statement; - } - - return true; - } - - function emitBlockFunctionBody(body: Block) { - write(" {"); - increaseIndent(); - - emitBodyWithDetachedComments(body, body.statements, - shouldEmitBlockFunctionBodyOnSingleLine(body) - ? emitBlockFunctionBodyOnSingleLine - : emitBlockFunctionBodyWorker); - - decreaseIndent(); - writeToken(SyntaxKind.CloseBraceToken, body.statements.end, body); - } - - function emitBlockFunctionBodyOnSingleLine(body: Block) { - emitBlockFunctionBodyWorker(body, /*emitBlockFunctionBodyOnSingleLine*/ true); - } - - function emitBlockFunctionBodyWorker(body: Block, emitBlockFunctionBodyOnSingleLine?: boolean) { - // Emit all the prologue directives (like "use strict"). - const statementOffset = emitPrologueDirectives(body.statements, /*startWithNewLine*/ true); - const helpersEmitted = emitHelpers(body); - - if (statementOffset === 0 && !helpersEmitted && emitBlockFunctionBodyOnSingleLine) { - decreaseIndent(); - emitList(body, body.statements, ListFormat.SingleLineFunctionBodyStatements); - increaseIndent(); - } - else { - emitList(body, body.statements, ListFormat.MultiLineFunctionBodyStatements, statementOffset); - } - } - - function emitClassDeclaration(node: ClassDeclaration) { - emitClassDeclarationOrExpression(node); - } - - function emitClassDeclarationOrExpression(node: ClassDeclaration | ClassExpression) { - emitDecorators(node, node.decorators); - emitModifiers(node, node.modifiers); - write("class"); - emitNodeWithPrefix(" ", node.name, emitIdentifierName); - - const indentedFlag = getEmitFlags(node) & EmitFlags.Indented; - if (indentedFlag) { - increaseIndent(); - } - - emitTypeParameters(node, node.typeParameters); - emitList(node, node.heritageClauses, ListFormat.ClassHeritageClauses); - - const savedTempFlags = tempFlags; - tempFlags = 0; - - write(" {"); - emitList(node, node.members, ListFormat.ClassMembers); - write("}"); - - if (indentedFlag) { - decreaseIndent(); - } - - tempFlags = savedTempFlags; - } - - function emitInterfaceDeclaration(node: InterfaceDeclaration) { - emitDecorators(node, node.decorators); - emitModifiers(node, node.modifiers); - write("interface "); - emit(node.name); - emitTypeParameters(node, node.typeParameters); - emitList(node, node.heritageClauses, ListFormat.HeritageClauses); - write(" {"); - emitList(node, node.members, ListFormat.InterfaceMembers); - write("}"); - } - - function emitTypeAliasDeclaration(node: TypeAliasDeclaration) { - emitDecorators(node, node.decorators); - emitModifiers(node, node.modifiers); - write("type "); - emit(node.name); - emitTypeParameters(node, node.typeParameters); - write(" = "); - emit(node.type); - write(";"); - } - - function emitEnumDeclaration(node: EnumDeclaration) { - emitModifiers(node, node.modifiers); - write("enum "); - emit(node.name); - - const savedTempFlags = tempFlags; - tempFlags = 0; - - write(" {"); - emitList(node, node.members, ListFormat.EnumMembers); - write("}"); - tempFlags = savedTempFlags; - } - - function emitModuleDeclaration(node: ModuleDeclaration) { - emitModifiers(node, node.modifiers); - write(node.flags & NodeFlags.Namespace ? "namespace " : "module "); - emit(node.name); - - let body = node.body; - while (body.kind === SyntaxKind.ModuleDeclaration) { - write("."); - emit((body).name); - body = (body).body; - } - - write(" "); - emit(body); - } - - function emitModuleBlock(node: ModuleBlock) { - if (isEmptyBlock(node)) { - write("{ }"); - } - else { - const savedTempFlags = tempFlags; - tempFlags = 0; - write("{"); - increaseIndent(); - emitBlockStatements(node); - write("}"); - tempFlags = savedTempFlags; - } - } - - function emitCaseBlock(node: CaseBlock) { - writeToken(SyntaxKind.OpenBraceToken, node.pos); - emitList(node, node.clauses, ListFormat.CaseBlockClauses); - writeToken(SyntaxKind.CloseBraceToken, node.clauses.end); - } - - function emitImportEqualsDeclaration(node: ImportEqualsDeclaration) { - emitModifiers(node, node.modifiers); - write("import "); - emit(node.name); - write(" = "); - emitModuleReference(node.moduleReference); - write(";"); - } - - function emitModuleReference(node: ModuleReference) { - if (node.kind === SyntaxKind.Identifier) { - emitExpression(node); - } - else { - emit(node); - } - } - - function emitImportDeclaration(node: ImportDeclaration) { - emitModifiers(node, node.modifiers); - write("import "); - if (node.importClause) { - emit(node.importClause); - write(" from "); - } - emitExpression(node.moduleSpecifier); - write(";"); - } - - function emitImportClause(node: ImportClause) { - emit(node.name); - if (node.name && node.namedBindings) { - write(", "); - } - emit(node.namedBindings); - } - - function emitNamespaceImport(node: NamespaceImport) { - write("* as "); - emit(node.name); - } - - function emitNamedImports(node: NamedImports) { - emitNamedImportsOrExports(node); - } - - function emitImportSpecifier(node: ImportSpecifier) { - emitImportOrExportSpecifier(node); - } - - function emitExportAssignment(node: ExportAssignment) { - write(node.isExportEquals ? "export = " : "export default "); - emitExpression(node.expression); - write(";"); - } - - function emitExportDeclaration(node: ExportDeclaration) { - write("export "); - if (node.exportClause) { - emit(node.exportClause); - } - else { - write("*"); - } - if (node.moduleSpecifier) { - write(" from "); - emitExpression(node.moduleSpecifier); - } - write(";"); - } - - function emitNamedExports(node: NamedExports) { - emitNamedImportsOrExports(node); - } - - function emitExportSpecifier(node: ExportSpecifier) { - emitImportOrExportSpecifier(node); - } - - function emitNamedImportsOrExports(node: NamedImportsOrExports) { - write("{"); - emitList(node, node.elements, ListFormat.NamedImportsOrExportsElements); - write("}"); - } - - function emitImportOrExportSpecifier(node: ImportOrExportSpecifier) { - if (node.propertyName) { - emit(node.propertyName); - write(" as "); - } - - emit(node.name); - } - - // - // Module references - // - - function emitExternalModuleReference(node: ExternalModuleReference) { - write("require("); - emitExpression(node.expression); - write(")"); - } - - // - // JSX - // - - function emitJsxElement(node: JsxElement) { - emit(node.openingElement); - emitList(node, node.children, ListFormat.JsxElementChildren); - emit(node.closingElement); - } - - function emitJsxSelfClosingElement(node: JsxSelfClosingElement) { - write("<"); - emitJsxTagName(node.tagName); - write(" "); - emitList(node, node.attributes, ListFormat.JsxElementAttributes); - write("/>"); - } - - function emitJsxOpeningElement(node: JsxOpeningElement) { - write("<"); - emitJsxTagName(node.tagName); - writeIfAny(node.attributes, " "); - emitList(node, node.attributes, ListFormat.JsxElementAttributes); - write(">"); - } - - function emitJsxText(node: JsxText) { - writer.writeLiteral(getTextOfNode(node, /*includeTrivia*/ true)); - } - - function emitJsxClosingElement(node: JsxClosingElement) { - write(""); - } - - function emitJsxAttribute(node: JsxAttribute) { - emit(node.name); - emitWithPrefix("=", node.initializer); - } - - function emitJsxSpreadAttribute(node: JsxSpreadAttribute) { - write("{..."); - emitExpression(node.expression); - write("}"); - } - - function emitJsxExpression(node: JsxExpression) { - if (node.expression) { - write("{"); - if (node.dotDotDotToken) { - write("..."); - } - emitExpression(node.expression); - write("}"); - } - } - - function emitJsxTagName(node: JsxTagNameExpression) { - if (node.kind === SyntaxKind.Identifier) { - emitExpression(node); - } - else { - emit(node); - } - } - - // - // Clauses - // - - function emitCaseClause(node: CaseClause) { - write("case "); - emitExpression(node.expression); - write(":"); - - emitCaseOrDefaultClauseStatements(node, node.statements); - } - - function emitDefaultClause(node: DefaultClause) { - write("default:"); - emitCaseOrDefaultClauseStatements(node, node.statements); - } - - function emitCaseOrDefaultClauseStatements(parentNode: Node, statements: NodeArray) { - const emitAsSingleStatement = - statements.length === 1 && - ( - // treat synthesized nodes as located on the same line for emit purposes - nodeIsSynthesized(parentNode) || - nodeIsSynthesized(statements[0]) || - rangeStartPositionsAreOnSameLine(parentNode, statements[0], currentSourceFile) - ); - - if (emitAsSingleStatement) { - write(" "); - emit(statements[0]); - } - else { - emitList(parentNode, statements, ListFormat.CaseOrDefaultClauseStatements); - } - } - - function emitHeritageClause(node: HeritageClause) { - write(" "); - writeTokenText(node.token); - write(" "); - emitList(node, node.types, ListFormat.HeritageClauseTypes); - } - - function emitCatchClause(node: CatchClause) { - writeLine(); - const openParenPos = writeToken(SyntaxKind.CatchKeyword, node.pos); - write(" "); - writeToken(SyntaxKind.OpenParenToken, openParenPos); - emit(node.variableDeclaration); - writeToken(SyntaxKind.CloseParenToken, node.variableDeclaration ? node.variableDeclaration.end : openParenPos); - write(" "); - emit(node.block); - } - - // - // Property assignments - // - - function emitPropertyAssignment(node: PropertyAssignment) { - emit(node.name); - write(": "); - // This is to ensure that we emit comment in the following case: - // For example: - // obj = { - // id: /*comment1*/ ()=>void - // } - // "comment1" is not considered to be leading comment for node.initializer - // but rather a trailing comment on the previous node. - const initializer = node.initializer; - if ((getEmitFlags(initializer) & EmitFlags.NoLeadingComments) === 0) { - const commentRange = getCommentRange(initializer); - emitTrailingCommentsOfPosition(commentRange.pos); - } - - emitExpression(initializer); - } - - function emitShorthandPropertyAssignment(node: ShorthandPropertyAssignment) { - emit(node.name); - if (node.objectAssignmentInitializer) { - write(" = "); - emitExpression(node.objectAssignmentInitializer); - } - } - - function emitSpreadAssignment(node: SpreadAssignment) { - if (node.expression) { - write("..."); - emitExpression(node.expression); - } - } - - // - // Enum - // - - function emitEnumMember(node: EnumMember) { - emit(node.name); - emitExpressionWithPrefix(" = ", node.initializer); - } - - // - // Top-level nodes - // - - function emitSourceFile(node: SourceFile) { - writeLine(); - emitShebang(); - emitBodyWithDetachedComments(node, node.statements, emitSourceFileWorker); - } - - function emitSourceFileWorker(node: SourceFile) { - const statements = node.statements; - const statementOffset = emitPrologueDirectives(statements); - const savedTempFlags = tempFlags; - tempFlags = 0; - emitHelpers(node); - emitList(node, statements, ListFormat.MultiLine, statementOffset); - tempFlags = savedTempFlags; - } - - // Transformation nodes - - function emitPartiallyEmittedExpression(node: PartiallyEmittedExpression) { - emitExpression(node.expression); - } - - /** - * Emits any prologue directives at the start of a Statement list, returning the - * number of prologue directives written to the output. - */ - function emitPrologueDirectives(statements: Node[], startWithNewLine?: boolean): number { - for (let i = 0; i < statements.length; i++) { - if (isPrologueDirective(statements[i])) { - if (startWithNewLine || i > 0) { - writeLine(); - } - emit(statements[i]); - } - else { - // return index of the first non prologue directive - return i; - } - } - - return statements.length; - } - - function emitHelpers(node: Node, isBundle?: boolean) { - const sourceFile = isSourceFile(node) ? node : currentSourceFile; - const shouldSkip = compilerOptions.noEmitHelpers || (sourceFile && getExternalHelpersModuleName(sourceFile) !== undefined); - const shouldBundle = isSourceFile(node) && !isOwnFileEmit; - + function emitHelpers(node: Node, writeLines: (text: string) => void) { let helpersEmitted = false; - const helpers = getEmitHelpers(node); - if (helpers) { - for (const helper of stableSort(helpers, compareEmitHelpers)) { - if (!helper.scoped) { - // Skip the helper if it can be skipped and the noEmitHelpers compiler - // option is set, or if it can be imported and the importHelpers compiler - // option is set. - if (shouldSkip) continue; + const bundle = node.kind === SyntaxKind.Bundle ? node : undefined; + const numNodes = bundle ? bundle.sourceFiles.length : 1; + for (let i = 0; i < numNodes; i++) { + const currentNode = bundle ? bundle.sourceFiles[i] : node; + const sourceFile = isSourceFile(currentNode) ? currentNode : currentSourceFile; + const shouldSkip = compilerOptions.noEmitHelpers || (sourceFile && getExternalHelpersModuleName(sourceFile) !== undefined); + const shouldBundle = isSourceFile(currentNode) && !isOwnFileEmit; + const helpers = getEmitHelpers(currentNode); + if (helpers) { + for (const helper of stableSort(helpers, compareEmitHelpers)) { + if (!helper.scoped) { + // Skip the helper if it can be skipped and the noEmitHelpers compiler + // option is set, or if it can be imported and the importHelpers compiler + // option is set. + if (shouldSkip) continue; - // Skip the helper if it can be bundled but hasn't already been emitted and we - // are emitting a bundled module. - if (shouldBundle) { - if (bundledHelpers.get(helper.name)) { - continue; + // Skip the helper if it can be bundled but hasn't already been emitted and we + // are emitting a bundled module. + if (shouldBundle) { + if (bundledHelpers.get(helper.name)) { + continue; + } + + bundledHelpers.set(helper.name, true); } - - bundledHelpers.set(helper.name, true); } - } - else if (isBundle) { - // Skip the helper if it is scoped and we are emitting bundled helpers - continue; - } + else if (bundle) { + // Skip the helper if it is scoped and we are emitting bundled helpers + continue; + } - writeLines(helper.text); - helpersEmitted = true; + writeLines(helper.text); + helpersEmitted = true; + } } } - if (helpersEmitted) { - writeLine(); - } - return helpersEmitted; } - - function writeLines(text: string): void { - const lines = text.split(/\r\n?|\n/g); - const indentation = guessIndentation(lines); - for (let i = 0; i < lines.length; i++) { - const line = indentation ? lines[i].slice(indentation) : lines[i]; - if (line.length) { - if (i > 0) { - writeLine(); - } - write(line); - } - } - } - - function guessIndentation(lines: string[]) { - let indentation: number; - for (const line of lines) { - for (let i = 0; i < line.length && (indentation === undefined || i < indentation); i++) { - if (!isWhiteSpace(line.charCodeAt(i))) { - if (indentation === undefined || i < indentation) { - indentation = i; - break; - } - } - } - } - return indentation; - } - - // - // Helpers - // - - function emitShebang() { - const shebang = getShebang(currentText); - if (shebang) { - write(shebang); - writeLine(); - } - } - - function emitModifiers(node: Node, modifiers: NodeArray) { - if (modifiers && modifiers.length) { - emitList(node, modifiers, ListFormat.Modifiers); - write(" "); - } - } - - function emitWithPrefix(prefix: string, node: Node) { - emitNodeWithPrefix(prefix, node, emit); - } - - function emitExpressionWithPrefix(prefix: string, node: Node) { - emitNodeWithPrefix(prefix, node, emitExpression); - } - - function emitNodeWithPrefix(prefix: string, node: Node, emit: (node: Node) => void) { - if (node) { - write(prefix); - emit(node); - } - } - - function emitWithSuffix(node: Node, suffix: string) { - if (node) { - emit(node); - write(suffix); - } - } - - function emitEmbeddedStatement(parent: Node, node: Statement) { - if (isBlock(node) || getEmitFlags(parent) & EmitFlags.SingleLine) { - write(" "); - emit(node); - } - else { - writeLine(); - increaseIndent(); - emit(node); - decreaseIndent(); - } - } - - function emitDecorators(parentNode: Node, decorators: NodeArray) { - emitList(parentNode, decorators, ListFormat.Decorators); - } - - function emitTypeArguments(parentNode: Node, typeArguments: NodeArray) { - emitList(parentNode, typeArguments, ListFormat.TypeArguments); - } - - function emitTypeParameters(parentNode: Node, typeParameters: NodeArray) { - emitList(parentNode, typeParameters, ListFormat.TypeParameters); - } - - function emitParameters(parentNode: Node, parameters: NodeArray) { - emitList(parentNode, parameters, ListFormat.Parameters); - } - - function emitParametersForArrow(parentNode: Node, parameters: NodeArray) { - if (parameters && - parameters.length === 1 && - parameters[0].type === undefined && - parameters[0].pos === parentNode.pos) { - emit(parameters[0]); - } - else { - emitParameters(parentNode, parameters); - } - } - - function emitParametersForIndexSignature(parentNode: Node, parameters: NodeArray) { - emitList(parentNode, parameters, ListFormat.IndexSignatureParameters); - } - - function emitList(parentNode: Node, children: NodeArray, format: ListFormat, start?: number, count?: number) { - emitNodeList(emit, parentNode, children, format, start, count); - } - - function emitExpressionList(parentNode: Node, children: NodeArray, format: ListFormat, start?: number, count?: number) { - emitNodeList(emitExpression, parentNode, children, format, start, count); - } - - function emitNodeList(emit: (node: Node) => void, parentNode: Node, children: NodeArray, format: ListFormat, start = 0, count = children ? children.length - start : 0) { - const isUndefined = children === undefined; - if (isUndefined && format & ListFormat.OptionalIfUndefined) { - return; - } - - const isEmpty = isUndefined || children.length === 0 || start >= children.length || count === 0; - if (isEmpty && format & ListFormat.OptionalIfEmpty) { - return; - } - - if (format & ListFormat.BracketsMask) { - write(getOpeningBracket(format)); - } - - if (isEmpty) { - // Write a line terminator if the parent node was multi-line - if (format & ListFormat.MultiLine) { - writeLine(); - } - else if (format & ListFormat.SpaceBetweenBraces) { - write(" "); - } - } - else { - // Write the opening line terminator or leading whitespace. - const mayEmitInterveningComments = (format & ListFormat.NoInterveningComments) === 0; - let shouldEmitInterveningComments = mayEmitInterveningComments; - if (shouldWriteLeadingLineTerminator(parentNode, children, format)) { - writeLine(); - shouldEmitInterveningComments = false; - } - else if (format & ListFormat.SpaceBetweenBraces) { - write(" "); - } - - // Increase the indent, if requested. - if (format & ListFormat.Indented) { - increaseIndent(); - } - - // Emit each child. - let previousSibling: Node; - let shouldDecreaseIndentAfterEmit: boolean; - const delimiter = getDelimiter(format); - for (let i = 0; i < count; i++) { - const child = children[start + i]; - - // Write the delimiter if this is not the first node. - if (previousSibling) { - write(delimiter); - - // Write either a line terminator or whitespace to separate the elements. - if (shouldWriteSeparatingLineTerminator(previousSibling, child, format)) { - // If a synthesized node in a single-line list starts on a new - // line, we should increase the indent. - if ((format & (ListFormat.LinesMask | ListFormat.Indented)) === ListFormat.SingleLine) { - increaseIndent(); - shouldDecreaseIndentAfterEmit = true; - } - - writeLine(); - shouldEmitInterveningComments = false; - } - else if (previousSibling && format & ListFormat.SpaceBetweenSiblings) { - write(" "); - } - } - - if (shouldEmitInterveningComments) { - const commentRange = getCommentRange(child); - emitTrailingCommentsOfPosition(commentRange.pos); - } - else { - shouldEmitInterveningComments = mayEmitInterveningComments; - } - - // Emit this child. - emit(child); - - if (shouldDecreaseIndentAfterEmit) { - decreaseIndent(); - shouldDecreaseIndentAfterEmit = false; - } - - previousSibling = child; - } - - // Write a trailing comma, if requested. - const hasTrailingComma = (format & ListFormat.AllowTrailingComma) && children.hasTrailingComma; - if (format & ListFormat.CommaDelimited && hasTrailingComma) { - write(","); - } - - // Decrease the indent, if requested. - if (format & ListFormat.Indented) { - decreaseIndent(); - } - - // Write the closing line terminator or closing whitespace. - if (shouldWriteClosingLineTerminator(parentNode, children, format)) { - writeLine(); - } - else if (format & ListFormat.SpaceBetweenBraces) { - write(" "); - } - } - - if (format & ListFormat.BracketsMask) { - write(getClosingBracket(format)); - } - } - - function writeLineOrSpace(node: Node) { - if (getEmitFlags(node) & EmitFlags.SingleLine) { - write(" "); - } - else { - writeLine(); - } - } - - function writeIfAny(nodes: NodeArray, text: string) { - if (nodes && nodes.length > 0) { - write(text); - } - } - - function writeIfPresent(node: Node, text: string) { - if (node !== undefined) { - write(text); - } - } - - function writeToken(token: SyntaxKind, pos: number, contextNode?: Node) { - return emitTokenWithSourceMap(contextNode, token, pos, writeTokenText); - } - - function writeTokenText(token: SyntaxKind, pos?: number) { - const tokenString = tokenToString(token); - write(tokenString); - return pos < 0 ? pos : pos + tokenString.length; - } - - function increaseIndentIf(value: boolean, valueToWriteWhenNotIndenting?: string) { - if (value) { - increaseIndent(); - writeLine(); - } - else if (valueToWriteWhenNotIndenting) { - write(valueToWriteWhenNotIndenting); - } - } - - // Helper function to decrease the indent if we previously indented. Allows multiple - // previous indent values to be considered at a time. This also allows caller to just - // call this once, passing in all their appropriate indent values, instead of needing - // to call this helper function multiple times. - function decreaseIndentIf(value1: boolean, value2?: boolean) { - if (value1) { - decreaseIndent(); - } - if (value2) { - decreaseIndent(); - } - } - - function shouldWriteLeadingLineTerminator(parentNode: Node, children: NodeArray, format: ListFormat) { - if (format & ListFormat.MultiLine) { - return true; - } - - if (format & ListFormat.PreserveLines) { - if (format & ListFormat.PreferNewLine) { - return true; - } - - const firstChild = children[0]; - if (firstChild === undefined) { - return !rangeIsOnSingleLine(parentNode, currentSourceFile); - } - else if (positionIsSynthesized(parentNode.pos) || nodeIsSynthesized(firstChild)) { - return synthesizedNodeStartsOnNewLine(firstChild, format); - } - else { - return !rangeStartPositionsAreOnSameLine(parentNode, firstChild, currentSourceFile); - } - } - else { - return false; - } - } - - function shouldWriteSeparatingLineTerminator(previousNode: Node, nextNode: Node, format: ListFormat) { - if (format & ListFormat.MultiLine) { - return true; - } - else if (format & ListFormat.PreserveLines) { - if (previousNode === undefined || nextNode === undefined) { - return false; - } - else if (nodeIsSynthesized(previousNode) || nodeIsSynthesized(nextNode)) { - return synthesizedNodeStartsOnNewLine(previousNode, format) || synthesizedNodeStartsOnNewLine(nextNode, format); - } - else { - return !rangeEndIsOnSameLineAsRangeStart(previousNode, nextNode, currentSourceFile); - } - } - else { - return nextNode.startsOnNewLine; - } - } - - function shouldWriteClosingLineTerminator(parentNode: Node, children: NodeArray, format: ListFormat) { - if (format & ListFormat.MultiLine) { - return (format & ListFormat.NoTrailingNewLine) === 0; - } - else if (format & ListFormat.PreserveLines) { - if (format & ListFormat.PreferNewLine) { - return true; - } - - const lastChild = lastOrUndefined(children); - if (lastChild === undefined) { - return !rangeIsOnSingleLine(parentNode, currentSourceFile); - } - else if (positionIsSynthesized(parentNode.pos) || nodeIsSynthesized(lastChild)) { - return synthesizedNodeStartsOnNewLine(lastChild, format); - } - else { - return !rangeEndPositionsAreOnSameLine(parentNode, lastChild, currentSourceFile); - } - } - else { - return false; - } - } - - function synthesizedNodeStartsOnNewLine(node: Node, format?: ListFormat) { - if (nodeIsSynthesized(node)) { - const startsOnNewLine = node.startsOnNewLine; - if (startsOnNewLine === undefined) { - return (format & ListFormat.PreferNewLine) !== 0; - } - - return startsOnNewLine; - } - - return (format & ListFormat.PreferNewLine) !== 0; - } - - function needsIndentation(parent: Node, node1: Node, node2: Node): boolean { - parent = skipSynthesizedParentheses(parent); - node1 = skipSynthesizedParentheses(node1); - node2 = skipSynthesizedParentheses(node2); - - // Always use a newline for synthesized code if the synthesizer desires it. - if (node2.startsOnNewLine) { - return true; - } - - return !nodeIsSynthesized(parent) - && !nodeIsSynthesized(node1) - && !nodeIsSynthesized(node2) - && !rangeEndIsOnSameLineAsRangeStart(node1, node2, currentSourceFile); - } - - function skipSynthesizedParentheses(node: Node) { - while (node.kind === SyntaxKind.ParenthesizedExpression && nodeIsSynthesized(node)) { - node = (node).expression; - } - - return node; - } - - function getTextOfNode(node: Node, includeTrivia?: boolean): string { - if (isGeneratedIdentifier(node)) { - return getGeneratedIdentifier(node); - } - else if (isIdentifier(node) && (nodeIsSynthesized(node) || !node.parent)) { - return unescapeIdentifier(node.text); - } - else if (node.kind === SyntaxKind.StringLiteral && (node).textSourceNode) { - return getTextOfNode((node).textSourceNode, includeTrivia); - } - else if (isLiteralExpression(node) && (nodeIsSynthesized(node) || !node.parent)) { - return node.text; - } - - return getSourceTextOfNodeFromSourceFile(currentSourceFile, node, includeTrivia); - } - - function getLiteralTextOfNode(node: LiteralLikeNode): string { - if (node.kind === SyntaxKind.StringLiteral && (node).textSourceNode) { - const textSourceNode = (node).textSourceNode; - if (isIdentifier(textSourceNode)) { - return "\"" + escapeNonAsciiCharacters(escapeString(getTextOfNode(textSourceNode))) + "\""; - } - else { - return getLiteralTextOfNode(textSourceNode); - } - } - - return getLiteralText(node, currentSourceFile, languageVersion); - } - - function isSingleLineEmptyBlock(block: Block) { - return !block.multiLine - && isEmptyBlock(block); - } - - function isEmptyBlock(block: BlockLike) { - return block.statements.length === 0 - && rangeEndIsOnSameLineAsRangeStart(block, block, currentSourceFile); - } - - function isUniqueName(name: string): boolean { - return !resolver.hasGlobalName(name) && - !currentFileIdentifiers.has(name) && - !generatedNameSet.has(name); - } - - function isUniqueLocalName(name: string, container: Node): boolean { - for (let node = container; isNodeDescendantOf(node, container); node = node.nextContainer) { - if (node.locals) { - const local = node.locals.get(name); - // We conservatively include alias symbols to cover cases where they're emitted as locals - if (local && local.flags & (SymbolFlags.Value | SymbolFlags.ExportValue | SymbolFlags.Alias)) { - return false; - } - } - } - return true; - } - - /** - * Return the next available name in the pattern _a ... _z, _0, _1, ... - * TempFlags._i or TempFlags._n may be used to express a preference for that dedicated name. - * Note that names generated by makeTempVariableName and makeUniqueName will never conflict. - */ - function makeTempVariableName(flags: TempFlags): string { - if (flags && !(tempFlags & flags)) { - const name = flags === TempFlags._i ? "_i" : "_n"; - if (isUniqueName(name)) { - tempFlags |= flags; - return name; - } - } - while (true) { - const count = tempFlags & TempFlags.CountMask; - tempFlags++; - // Skip over 'i' and 'n' - if (count !== 8 && count !== 13) { - const name = count < 26 - ? "_" + String.fromCharCode(CharacterCodes.a + count) - : "_" + (count - 26); - if (isUniqueName(name)) { - return name; - } - } - } - } - - // Generate a name that is unique within the current file and doesn't conflict with any names - // in global scope. The name is formed by adding an '_n' suffix to the specified base name, - // where n is a positive integer. Note that names generated by makeTempVariableName and - // makeUniqueName are guaranteed to never conflict. - function makeUniqueName(baseName: string): string { - // Find the first unique 'name_n', where n is a positive number - if (baseName.charCodeAt(baseName.length - 1) !== CharacterCodes._) { - baseName += "_"; - } - let i = 1; - while (true) { - const generatedName = baseName + i; - if (isUniqueName(generatedName)) { - generatedNameSet.set(generatedName, generatedName); - return generatedName; - } - i++; - } - } - - function generateNameForModuleOrEnum(node: ModuleDeclaration | EnumDeclaration) { - const name = getTextOfNode(node.name); - // Use module/enum name itself if it is unique, otherwise make a unique variation - return isUniqueLocalName(name, node) ? name : makeUniqueName(name); - } - - function generateNameForImportOrExportDeclaration(node: ImportDeclaration | ExportDeclaration) { - const expr = getExternalModuleName(node); - const baseName = expr.kind === SyntaxKind.StringLiteral ? - escapeIdentifier(makeIdentifierFromModuleName((expr).text)) : "module"; - return makeUniqueName(baseName); - } - - function generateNameForExportDefault() { - return makeUniqueName("default"); - } - - function generateNameForClassExpression() { - return makeUniqueName("class"); - } - - function generateNameForMethodOrAccessor(node: MethodDeclaration | AccessorDeclaration) { - if (isIdentifier(node.name)) { - return generateNameForNodeCached(node.name); - } - return makeTempVariableName(TempFlags.Auto); - } - - /** - * Generates a unique name from a node. - * - * @param node A node. - */ - function generateNameForNode(node: Node): string { - switch (node.kind) { - case SyntaxKind.Identifier: - return makeUniqueName(getTextOfNode(node)); - case SyntaxKind.ModuleDeclaration: - case SyntaxKind.EnumDeclaration: - return generateNameForModuleOrEnum(node); - case SyntaxKind.ImportDeclaration: - case SyntaxKind.ExportDeclaration: - return generateNameForImportOrExportDeclaration(node); - case SyntaxKind.FunctionDeclaration: - case SyntaxKind.ClassDeclaration: - case SyntaxKind.ExportAssignment: - return generateNameForExportDefault(); - case SyntaxKind.ClassExpression: - return generateNameForClassExpression(); - case SyntaxKind.MethodDeclaration: - case SyntaxKind.GetAccessor: - case SyntaxKind.SetAccessor: - return generateNameForMethodOrAccessor(node); - default: - return makeTempVariableName(TempFlags.Auto); - } - } - - /** - * Generates a unique identifier for a node. - * - * @param name A generated name. - */ - function generateName(name: Identifier) { - switch (name.autoGenerateKind) { - case GeneratedIdentifierKind.Auto: - return makeTempVariableName(TempFlags.Auto); - case GeneratedIdentifierKind.Loop: - return makeTempVariableName(TempFlags._i); - case GeneratedIdentifierKind.Unique: - return makeUniqueName(name.text); - } - - Debug.fail("Unsupported GeneratedIdentifierKind."); - } - - /** - * Gets the node from which a name should be generated. - * - * @param name A generated name wrapper. - */ - function getNodeForGeneratedName(name: Identifier) { - const autoGenerateId = name.autoGenerateId; - let node = name as Node; - let original = node.original; - while (original) { - node = original; - - // if "node" is a different generated name (having a different - // "autoGenerateId"), use it and stop traversing. - if (isIdentifier(node) - && node.autoGenerateKind === GeneratedIdentifierKind.Node - && node.autoGenerateId !== autoGenerateId) { - break; - } - - original = node.original; - } - - // otherwise, return the original node for the source; - return node; - } - - function generateNameForNodeCached(node: Node) { - const nodeId = getNodeId(node); - return nodeIdToGeneratedName[nodeId] || (nodeIdToGeneratedName[nodeId] = unescapeIdentifier(generateNameForNode(node))); - } - - /** - * Gets the generated identifier text from a generated identifier. - * - * @param name The generated identifier. - */ - function getGeneratedIdentifier(name: Identifier) { - if (name.autoGenerateKind === GeneratedIdentifierKind.Node) { - // Generated names generate unique names based on their original node - // and are cached based on that node's id - const node = getNodeForGeneratedName(name); - return generateNameForNodeCached(node); - } - else { - // Auto, Loop, and Unique names are cached based on their unique - // autoGenerateId. - const autoGenerateId = name.autoGenerateId; - return autoGeneratedIdToGeneratedName[autoGenerateId] || (autoGeneratedIdToGeneratedName[autoGenerateId] = unescapeIdentifier(generateName(name))); - } - } - - function createDelimiterMap() { - const delimiters: string[] = []; - delimiters[ListFormat.None] = ""; - delimiters[ListFormat.CommaDelimited] = ","; - delimiters[ListFormat.BarDelimited] = " |"; - delimiters[ListFormat.AmpersandDelimited] = " &"; - return delimiters; - } - - function getDelimiter(format: ListFormat) { - return delimiters[format & ListFormat.DelimitersMask]; - } - - function createBracketsMap() { - const brackets: string[][] = []; - brackets[ListFormat.Braces] = ["{", "}"]; - brackets[ListFormat.Parenthesis] = ["(", ")"]; - brackets[ListFormat.AngleBrackets] = ["<", ">"]; - brackets[ListFormat.SquareBrackets] = ["[", "]"]; - return brackets; - } - - function getOpeningBracket(format: ListFormat) { - return brackets[format & ListFormat.BracketsMask][0]; - } - - function getClosingBracket(format: ListFormat) { - return brackets[format & ListFormat.BracketsMask][1]; - } } - - const enum ListFormat { - None = 0, - - // Line separators - SingleLine = 0, // Prints the list on a single line (default). - MultiLine = 1 << 0, // Prints the list on multiple lines. - PreserveLines = 1 << 1, // Prints the list using line preservation if possible. - LinesMask = SingleLine | MultiLine | PreserveLines, - - // Delimiters - NotDelimited = 0, // There is no delimiter between list items (default). - BarDelimited = 1 << 2, // Each list item is space-and-bar (" |") delimited. - AmpersandDelimited = 1 << 3, // Each list item is space-and-ampersand (" &") delimited. - CommaDelimited = 1 << 4, // Each list item is comma (",") delimited. - DelimitersMask = BarDelimited | AmpersandDelimited | CommaDelimited, - - AllowTrailingComma = 1 << 5, // Write a trailing comma (",") if present. - - // Whitespace - Indented = 1 << 6, // The list should be indented. - SpaceBetweenBraces = 1 << 7, // Inserts a space after the opening brace and before the closing brace. - SpaceBetweenSiblings = 1 << 8, // Inserts a space between each sibling node. - - // Brackets/Braces - Braces = 1 << 9, // The list is surrounded by "{" and "}". - Parenthesis = 1 << 10, // The list is surrounded by "(" and ")". - AngleBrackets = 1 << 11, // The list is surrounded by "<" and ">". - SquareBrackets = 1 << 12, // The list is surrounded by "[" and "]". - BracketsMask = Braces | Parenthesis | AngleBrackets | SquareBrackets, - - OptionalIfUndefined = 1 << 13, // Do not emit brackets if the list is undefined. - OptionalIfEmpty = 1 << 14, // Do not emit brackets if the list is empty. - Optional = OptionalIfUndefined | OptionalIfEmpty, - - // Other - PreferNewLine = 1 << 15, // Prefer adding a LineTerminator between synthesized nodes. - NoTrailingNewLine = 1 << 16, // Do not emit a trailing NewLine for a MultiLine list. - NoInterveningComments = 1 << 17, // Do not emit comments between each node - - // Precomputed Formats - Modifiers = SingleLine | SpaceBetweenSiblings, - HeritageClauses = SingleLine | SpaceBetweenSiblings, - TypeLiteralMembers = MultiLine | Indented, - TupleTypeElements = CommaDelimited | SpaceBetweenSiblings | SingleLine | Indented, - UnionTypeConstituents = BarDelimited | SpaceBetweenSiblings | SingleLine, - IntersectionTypeConstituents = AmpersandDelimited | SpaceBetweenSiblings | SingleLine, - ObjectBindingPatternElements = SingleLine | AllowTrailingComma | SpaceBetweenBraces | CommaDelimited | SpaceBetweenSiblings, - ArrayBindingPatternElements = SingleLine | AllowTrailingComma | CommaDelimited | SpaceBetweenSiblings, - ObjectLiteralExpressionProperties = PreserveLines | CommaDelimited | SpaceBetweenSiblings | SpaceBetweenBraces | Indented | Braces, - ArrayLiteralExpressionElements = PreserveLines | CommaDelimited | SpaceBetweenSiblings | AllowTrailingComma | Indented | SquareBrackets, - CallExpressionArguments = CommaDelimited | SpaceBetweenSiblings | SingleLine | Parenthesis, - NewExpressionArguments = CommaDelimited | SpaceBetweenSiblings | SingleLine | Parenthesis | OptionalIfUndefined, - TemplateExpressionSpans = SingleLine | NoInterveningComments, - SingleLineBlockStatements = SpaceBetweenBraces | SpaceBetweenSiblings | SingleLine, - MultiLineBlockStatements = Indented | MultiLine, - VariableDeclarationList = CommaDelimited | SpaceBetweenSiblings | SingleLine, - SingleLineFunctionBodyStatements = SingleLine | SpaceBetweenSiblings | SpaceBetweenBraces, - MultiLineFunctionBodyStatements = MultiLine, - ClassHeritageClauses = SingleLine | SpaceBetweenSiblings, - ClassMembers = Indented | MultiLine, - InterfaceMembers = Indented | MultiLine, - EnumMembers = CommaDelimited | Indented | MultiLine, - CaseBlockClauses = Indented | MultiLine, - NamedImportsOrExportsElements = CommaDelimited | SpaceBetweenSiblings | AllowTrailingComma | SingleLine | SpaceBetweenBraces, - JsxElementChildren = SingleLine | NoInterveningComments, - JsxElementAttributes = SingleLine | SpaceBetweenSiblings | NoInterveningComments, - CaseOrDefaultClauseStatements = Indented | MultiLine | NoTrailingNewLine | OptionalIfEmpty, - HeritageClauseTypes = CommaDelimited | SpaceBetweenSiblings | SingleLine, - SourceFileStatements = MultiLine | NoTrailingNewLine, - Decorators = MultiLine | Optional, - TypeArguments = CommaDelimited | SpaceBetweenSiblings | SingleLine | Indented | AngleBrackets | Optional, - TypeParameters = CommaDelimited | SpaceBetweenSiblings | SingleLine | Indented | AngleBrackets | Optional, - Parameters = CommaDelimited | SpaceBetweenSiblings | SingleLine | Indented | Parenthesis, - IndexSignatureParameters = CommaDelimited | SpaceBetweenSiblings | SingleLine | Indented | SquareBrackets, - } -} +} \ No newline at end of file diff --git a/src/compiler/factory.ts b/src/compiler/factory.ts index f63094ae16d..f2a8de3a93b 100644 --- a/src/compiler/factory.ts +++ b/src/compiler/factory.ts @@ -1530,6 +1530,19 @@ namespace ts { return node; } + export function createBundle(sourceFiles: SourceFile[]) { + const node = createNode(SyntaxKind.Bundle); + node.sourceFiles = sourceFiles; + return node; + } + + export function updateBundle(node: Bundle, sourceFiles: SourceFile[]) { + if (node.sourceFiles !== sourceFiles) { + return createBundle(sourceFiles); + } + return node; + } + // Compound nodes export function createComma(left: Expression, right: Expression) { diff --git a/src/compiler/printer.ts b/src/compiler/printer.ts new file mode 100644 index 00000000000..9ae824dac67 --- /dev/null +++ b/src/compiler/printer.ts @@ -0,0 +1,2659 @@ +/// + +namespace ts { + // Flags enum to track count of temp variables and a few dedicated names + const enum TempFlags { + Auto = 0x00000000, // No preferred name + CountMask = 0x0FFFFFFF, // Temp variable counter + _i = 0x10000000, // Use/preference flag for '_i' + } + + const delimiters = createDelimiterMap(); + const brackets = createBracketsMap(); + + export function createPrinter(writer: EmitTextWriter, compilerOptions: CompilerOptions, printerOptions: PrinterOptions = {}): Printer { + const languageVersion = getEmitScriptTarget(compilerOptions); + const moduleKind = getEmitModuleKind(compilerOptions); + const { + hasGlobalName, + onEmitSourceMapOfNode, + onEmitSourceMapOfToken, + onEmitCommentsOfNode, + onEmitDetachedCommentsOfNode, + onEmitTrailingCommentsOfPosition, + onEmitNode, + onEmitHelpers, + onSetSourceFile, + onSubstituteNode, + } = printerOptions; + const { + write, + writeLine, + increaseIndent, + decreaseIndent + } = writer; + + let currentSourceFile: SourceFile; + let nodeIdToGeneratedName: string[]; // Map of generated names for specific nodes. + let autoGeneratedIdToGeneratedName: string[]; // Map of generated names for temp and loop variables. + let generatedNames: Map; // Set of names generated by the NameGenerator. + let tempFlagsStack: TempFlags[]; // Stack of enclosing name generation scopes. + let tempFlags: TempFlags; // TempFlags for the current name generation scope. + + return { + printNode, + printFile, + printBundle + }; + + function printNode(hint: EmitHint, node: Node, sourceFile: SourceFile) { + print(hint, node, sourceFile); + resetGeneratedNames(); + } + + function printBundle(bundle: Bundle) { + if (moduleKind) { + emitHelpersIndirect(bundle); + } + for (const sourceFile of bundle.sourceFiles) { + print(EmitHint.SourceFile, sourceFile, sourceFile); + } + resetGeneratedNames(); + } + + function printFile(sourceFile: SourceFile) { + print(EmitHint.SourceFile, sourceFile, sourceFile); + resetGeneratedNames(); + } + + function print(hint: EmitHint, node: Node, sourceFile: SourceFile) { + setSourceFile(sourceFile); + pipelineEmitWithNotification(hint, node); + } + + function setSourceFile(sourceFile: SourceFile) { + currentSourceFile = sourceFile; + + if (onSetSourceFile) { + onSetSourceFile(sourceFile); + } + } + + function emit(node: Node, hint = EmitHint.Unspecified) { + pipelineEmitWithNotification(hint, node); + } + + function emitIdentifierName(node: Identifier) { + pipelineEmitWithNotification(EmitHint.IdentifierName, node); + } + + function emitExpression(node: Expression) { + pipelineEmitWithNotification(EmitHint.Expression, node); + } + + function pipelineEmitWithNotification(hint: EmitHint, node: Node) { + if (onEmitNode) { + onEmitNode(hint, node, pipelineEmitWithComments); + } + else { + pipelineEmitWithComments(hint, node); + } + } + + function pipelineEmitWithComments(hint: EmitHint, node: Node) { + if (onEmitCommentsOfNode && hint !== EmitHint.SourceFile) { + onEmitCommentsOfNode(hint, node, pipelineEmitWithSourceMap); + } + else { + pipelineEmitWithSourceMap(hint, node); + } + } + + function pipelineEmitWithSourceMap(hint: EmitHint, node: Node) { + if (onEmitSourceMapOfNode && hint !== EmitHint.SourceFile && hint !== EmitHint.IdentifierName) { + onEmitSourceMapOfNode(hint, node, pipelineEmitWithSubstitution); + } + else { + pipelineEmitWithSubstitution(hint, node); + } + } + + function pipelineEmitWithSubstitution(hint: EmitHint, node: Node) { + if (onSubstituteNode) { + onSubstituteNode(hint, node, pipelineEmitWithHint); + } + else { + pipelineEmitWithHint(hint, node); + } + } + + function pipelineEmitWithHint(hint: EmitHint, node: Node): void { + switch (hint) { + case EmitHint.SourceFile: return pipelineEmitSourceFile(node); + case EmitHint.IdentifierName: return pipelineEmitIdentifierName(node); + case EmitHint.Expression: return pipelineEmitExpression(node); + case EmitHint.Unspecified: return pipelineEmitUnspecified(node); + } + } + + function pipelineEmitSourceFile(node: Node): void { + Debug.assertNode(node, isSourceFile); + emitSourceFile(node); + } + + function pipelineEmitIdentifierName(node: Node): void { + Debug.assertNode(node, isIdentifier); + emitIdentifier(node); + } + + function pipelineEmitUnspecified(node: Node): void { + const kind = node.kind; + switch (kind) { + // Pseudo-literals + case SyntaxKind.TemplateHead: + case SyntaxKind.TemplateMiddle: + case SyntaxKind.TemplateTail: + return emitLiteral(node); + + // Identifiers + case SyntaxKind.Identifier: + return emitIdentifier(node); + + // Reserved words + case SyntaxKind.ConstKeyword: + case SyntaxKind.DefaultKeyword: + case SyntaxKind.ExportKeyword: + case SyntaxKind.VoidKeyword: + + // Strict mode reserved words + case SyntaxKind.PrivateKeyword: + case SyntaxKind.ProtectedKeyword: + case SyntaxKind.PublicKeyword: + case SyntaxKind.StaticKeyword: + + // Contextual keywords + case SyntaxKind.AbstractKeyword: + case SyntaxKind.AsKeyword: + case SyntaxKind.AnyKeyword: + case SyntaxKind.AsyncKeyword: + case SyntaxKind.AwaitKeyword: + case SyntaxKind.BooleanKeyword: + case SyntaxKind.ConstructorKeyword: + case SyntaxKind.DeclareKeyword: + case SyntaxKind.GetKeyword: + case SyntaxKind.IsKeyword: + case SyntaxKind.ModuleKeyword: + case SyntaxKind.NamespaceKeyword: + case SyntaxKind.NeverKeyword: + case SyntaxKind.ReadonlyKeyword: + case SyntaxKind.RequireKeyword: + case SyntaxKind.NumberKeyword: + case SyntaxKind.SetKeyword: + case SyntaxKind.StringKeyword: + case SyntaxKind.SymbolKeyword: + case SyntaxKind.TypeKeyword: + case SyntaxKind.UndefinedKeyword: + case SyntaxKind.FromKeyword: + case SyntaxKind.GlobalKeyword: + case SyntaxKind.OfKeyword: + writeTokenText(kind); + return; + + // Parse tree nodes + + // Names + case SyntaxKind.QualifiedName: + return emitQualifiedName(node); + case SyntaxKind.ComputedPropertyName: + return emitComputedPropertyName(node); + + // Signature elements + case SyntaxKind.TypeParameter: + return emitTypeParameter(node); + case SyntaxKind.Parameter: + return emitParameter(node); + case SyntaxKind.Decorator: + return emitDecorator(node); + + // Type members + case SyntaxKind.PropertySignature: + return emitPropertySignature(node); + case SyntaxKind.PropertyDeclaration: + return emitPropertyDeclaration(node); + case SyntaxKind.MethodSignature: + return emitMethodSignature(node); + case SyntaxKind.MethodDeclaration: + return emitMethodDeclaration(node); + case SyntaxKind.Constructor: + return emitConstructor(node); + case SyntaxKind.GetAccessor: + case SyntaxKind.SetAccessor: + return emitAccessorDeclaration(node); + case SyntaxKind.CallSignature: + return emitCallSignature(node); + case SyntaxKind.ConstructSignature: + return emitConstructSignature(node); + case SyntaxKind.IndexSignature: + return emitIndexSignature(node); + + // Types + case SyntaxKind.TypePredicate: + return emitTypePredicate(node); + case SyntaxKind.TypeReference: + return emitTypeReference(node); + case SyntaxKind.FunctionType: + return emitFunctionType(node); + case SyntaxKind.ConstructorType: + return emitConstructorType(node); + case SyntaxKind.TypeQuery: + return emitTypeQuery(node); + case SyntaxKind.TypeLiteral: + return emitTypeLiteral(node); + case SyntaxKind.ArrayType: + return emitArrayType(node); + case SyntaxKind.TupleType: + return emitTupleType(node); + case SyntaxKind.UnionType: + return emitUnionType(node); + case SyntaxKind.IntersectionType: + return emitIntersectionType(node); + case SyntaxKind.ParenthesizedType: + return emitParenthesizedType(node); + case SyntaxKind.ExpressionWithTypeArguments: + return emitExpressionWithTypeArguments(node); + case SyntaxKind.ThisType: + return emitThisType(); + case SyntaxKind.TypeOperator: + return emitTypeOperator(node); + case SyntaxKind.IndexedAccessType: + return emitIndexedAccessType(node); + case SyntaxKind.MappedType: + return emitMappedType(node); + case SyntaxKind.LiteralType: + return emitLiteralType(node); + + // Binding patterns + case SyntaxKind.ObjectBindingPattern: + return emitObjectBindingPattern(node); + case SyntaxKind.ArrayBindingPattern: + return emitArrayBindingPattern(node); + case SyntaxKind.BindingElement: + return emitBindingElement(node); + + // Misc + case SyntaxKind.TemplateSpan: + return emitTemplateSpan(node); + case SyntaxKind.SemicolonClassElement: + return emitSemicolonClassElement(); + + // Statements + case SyntaxKind.Block: + return emitBlock(node); + case SyntaxKind.VariableStatement: + return emitVariableStatement(node); + case SyntaxKind.EmptyStatement: + return emitEmptyStatement(); + case SyntaxKind.ExpressionStatement: + return emitExpressionStatement(node); + case SyntaxKind.IfStatement: + return emitIfStatement(node); + case SyntaxKind.DoStatement: + return emitDoStatement(node); + case SyntaxKind.WhileStatement: + return emitWhileStatement(node); + case SyntaxKind.ForStatement: + return emitForStatement(node); + case SyntaxKind.ForInStatement: + return emitForInStatement(node); + case SyntaxKind.ForOfStatement: + return emitForOfStatement(node); + case SyntaxKind.ContinueStatement: + return emitContinueStatement(node); + case SyntaxKind.BreakStatement: + return emitBreakStatement(node); + case SyntaxKind.ReturnStatement: + return emitReturnStatement(node); + case SyntaxKind.WithStatement: + return emitWithStatement(node); + case SyntaxKind.SwitchStatement: + return emitSwitchStatement(node); + case SyntaxKind.LabeledStatement: + return emitLabeledStatement(node); + case SyntaxKind.ThrowStatement: + return emitThrowStatement(node); + case SyntaxKind.TryStatement: + return emitTryStatement(node); + case SyntaxKind.DebuggerStatement: + return emitDebuggerStatement(node); + + // Declarations + case SyntaxKind.VariableDeclaration: + return emitVariableDeclaration(node); + case SyntaxKind.VariableDeclarationList: + return emitVariableDeclarationList(node); + case SyntaxKind.FunctionDeclaration: + return emitFunctionDeclaration(node); + case SyntaxKind.ClassDeclaration: + return emitClassDeclaration(node); + case SyntaxKind.InterfaceDeclaration: + return emitInterfaceDeclaration(node); + case SyntaxKind.TypeAliasDeclaration: + return emitTypeAliasDeclaration(node); + case SyntaxKind.EnumDeclaration: + return emitEnumDeclaration(node); + case SyntaxKind.ModuleDeclaration: + return emitModuleDeclaration(node); + case SyntaxKind.ModuleBlock: + return emitModuleBlock(node); + case SyntaxKind.CaseBlock: + return emitCaseBlock(node); + case SyntaxKind.ImportEqualsDeclaration: + return emitImportEqualsDeclaration(node); + case SyntaxKind.ImportDeclaration: + return emitImportDeclaration(node); + case SyntaxKind.ImportClause: + return emitImportClause(node); + case SyntaxKind.NamespaceImport: + return emitNamespaceImport(node); + case SyntaxKind.NamedImports: + return emitNamedImports(node); + case SyntaxKind.ImportSpecifier: + return emitImportSpecifier(node); + case SyntaxKind.ExportAssignment: + return emitExportAssignment(node); + case SyntaxKind.ExportDeclaration: + return emitExportDeclaration(node); + case SyntaxKind.NamedExports: + return emitNamedExports(node); + case SyntaxKind.ExportSpecifier: + return emitExportSpecifier(node); + case SyntaxKind.MissingDeclaration: + return; + + // Module references + case SyntaxKind.ExternalModuleReference: + return emitExternalModuleReference(node); + + // JSX (non-expression) + case SyntaxKind.JsxText: + return emitJsxText(node); + case SyntaxKind.JsxOpeningElement: + return emitJsxOpeningElement(node); + case SyntaxKind.JsxClosingElement: + return emitJsxClosingElement(node); + case SyntaxKind.JsxAttribute: + return emitJsxAttribute(node); + case SyntaxKind.JsxSpreadAttribute: + return emitJsxSpreadAttribute(node); + case SyntaxKind.JsxExpression: + return emitJsxExpression(node); + + // Clauses + case SyntaxKind.CaseClause: + return emitCaseClause(node); + case SyntaxKind.DefaultClause: + return emitDefaultClause(node); + case SyntaxKind.HeritageClause: + return emitHeritageClause(node); + case SyntaxKind.CatchClause: + return emitCatchClause(node); + + // Property assignments + case SyntaxKind.PropertyAssignment: + return emitPropertyAssignment(node); + case SyntaxKind.ShorthandPropertyAssignment: + return emitShorthandPropertyAssignment(node); + case SyntaxKind.SpreadAssignment: + return emitSpreadAssignment(node as SpreadAssignment); + + // Enum + case SyntaxKind.EnumMember: + return emitEnumMember(node); + + // JSDoc nodes (ignored) + // Transformation nodes (ignored) + } + + // If the node is an expression, try to emit it as an expression with + // substitution. + if (isExpression(node)) { + return pipelineEmitWithSubstitution(EmitHint.Expression, node); + } + } + + function pipelineEmitExpression(node: Node): void { + const kind = node.kind; + switch (kind) { + // Literals + case SyntaxKind.NumericLiteral: + return emitNumericLiteral(node); + + case SyntaxKind.StringLiteral: + case SyntaxKind.RegularExpressionLiteral: + case SyntaxKind.NoSubstitutionTemplateLiteral: + return emitLiteral(node); + + // Identifiers + case SyntaxKind.Identifier: + return emitIdentifier(node); + + // Reserved words + case SyntaxKind.FalseKeyword: + case SyntaxKind.NullKeyword: + case SyntaxKind.SuperKeyword: + case SyntaxKind.TrueKeyword: + case SyntaxKind.ThisKeyword: + writeTokenText(kind); + return; + + // Expressions + case SyntaxKind.ArrayLiteralExpression: + return emitArrayLiteralExpression(node); + case SyntaxKind.ObjectLiteralExpression: + return emitObjectLiteralExpression(node); + case SyntaxKind.PropertyAccessExpression: + return emitPropertyAccessExpression(node); + case SyntaxKind.ElementAccessExpression: + return emitElementAccessExpression(node); + case SyntaxKind.CallExpression: + return emitCallExpression(node); + case SyntaxKind.NewExpression: + return emitNewExpression(node); + case SyntaxKind.TaggedTemplateExpression: + return emitTaggedTemplateExpression(node); + case SyntaxKind.TypeAssertionExpression: + return emitTypeAssertionExpression(node); + case SyntaxKind.ParenthesizedExpression: + return emitParenthesizedExpression(node); + case SyntaxKind.FunctionExpression: + return emitFunctionExpression(node); + case SyntaxKind.ArrowFunction: + return emitArrowFunction(node); + case SyntaxKind.DeleteExpression: + return emitDeleteExpression(node); + case SyntaxKind.TypeOfExpression: + return emitTypeOfExpression(node); + case SyntaxKind.VoidExpression: + return emitVoidExpression(node); + case SyntaxKind.AwaitExpression: + return emitAwaitExpression(node); + case SyntaxKind.PrefixUnaryExpression: + return emitPrefixUnaryExpression(node); + case SyntaxKind.PostfixUnaryExpression: + return emitPostfixUnaryExpression(node); + case SyntaxKind.BinaryExpression: + return emitBinaryExpression(node); + case SyntaxKind.ConditionalExpression: + return emitConditionalExpression(node); + case SyntaxKind.TemplateExpression: + return emitTemplateExpression(node); + case SyntaxKind.YieldExpression: + return emitYieldExpression(node); + case SyntaxKind.SpreadElement: + return emitSpreadExpression(node); + case SyntaxKind.ClassExpression: + return emitClassExpression(node); + case SyntaxKind.OmittedExpression: + return; + case SyntaxKind.AsExpression: + return emitAsExpression(node); + case SyntaxKind.NonNullExpression: + return emitNonNullExpression(node); + case SyntaxKind.MetaProperty: + return emitMetaProperty(node); + + // JSX + case SyntaxKind.JsxElement: + return emitJsxElement(node); + case SyntaxKind.JsxSelfClosingElement: + return emitJsxSelfClosingElement(node); + + // Transformation nodes + case SyntaxKind.PartiallyEmittedExpression: + return emitPartiallyEmittedExpression(node); + } + } + + function emitBodyIndirect(node: Node, elements: NodeArray, emitCallback: (node: Node) => void): void { + if (onEmitDetachedCommentsOfNode) { + onEmitDetachedCommentsOfNode(node, elements, emitCallback); + } + else { + emitCallback(node); + } + } + + function emitHelpersIndirect(node: Node) { + if (onEmitHelpers) { + onEmitHelpers(node, writeLines); + } + } + + // + // Literals/Pseudo-literals + // + + // SyntaxKind.NumericLiteral + function emitNumericLiteral(node: NumericLiteral) { + emitLiteral(node); + if (node.trailingComment) { + write(` /*${node.trailingComment}*/`); + } + } + + // SyntaxKind.StringLiteral + // SyntaxKind.RegularExpressionLiteral + // SyntaxKind.NoSubstitutionTemplateLiteral + // SyntaxKind.TemplateHead + // SyntaxKind.TemplateMiddle + // SyntaxKind.TemplateTail + function emitLiteral(node: LiteralLikeNode) { + const text = getLiteralTextOfNode(node); + if ((compilerOptions.sourceMap || compilerOptions.inlineSourceMap) + && (node.kind === SyntaxKind.StringLiteral || isTemplateLiteralKind(node.kind))) { + writer.writeLiteral(text); + } + else { + write(text); + } + } + + // + // Identifiers + // + + function emitIdentifier(node: Identifier) { + write(getTextOfNode(node, /*includeTrivia*/ false)); + } + + // + // Names + // + + function emitQualifiedName(node: QualifiedName) { + emitEntityName(node.left); + write("."); + emit(node.right); + } + + function emitEntityName(node: EntityName) { + if (node.kind === SyntaxKind.Identifier) { + emitExpression(node); + } + else { + emit(node); + } + } + + function emitComputedPropertyName(node: ComputedPropertyName) { + write("["); + emitExpression(node.expression); + write("]"); + } + + // + // Signature elements + // + + function emitTypeParameter(node: TypeParameterDeclaration) { + emit(node.name); + emitWithPrefix(" extends ", node.constraint); + } + + function emitParameter(node: ParameterDeclaration) { + emitDecorators(node, node.decorators); + emitModifiers(node, node.modifiers); + writeIfPresent(node.dotDotDotToken, "..."); + emit(node.name); + writeIfPresent(node.questionToken, "?"); + emitExpressionWithPrefix(" = ", node.initializer); + emitWithPrefix(": ", node.type); + } + + function emitDecorator(decorator: Decorator) { + write("@"); + emitExpression(decorator.expression); + } + + // + // Type members + // + + function emitPropertySignature(node: PropertySignature) { + emitDecorators(node, node.decorators); + emitModifiers(node, node.modifiers); + emit(node.name); + writeIfPresent(node.questionToken, "?"); + emitWithPrefix(": ", node.type); + write(";"); + } + + function emitPropertyDeclaration(node: PropertyDeclaration) { + emitDecorators(node, node.decorators); + emitModifiers(node, node.modifiers); + emit(node.name); + emitWithPrefix(": ", node.type); + emitExpressionWithPrefix(" = ", node.initializer); + write(";"); + } + + function emitMethodSignature(node: MethodSignature) { + emitDecorators(node, node.decorators); + emitModifiers(node, node.modifiers); + emit(node.name); + writeIfPresent(node.questionToken, "?"); + emitTypeParameters(node, node.typeParameters); + emitParameters(node, node.parameters); + emitWithPrefix(": ", node.type); + write(";"); + } + + function emitMethodDeclaration(node: MethodDeclaration) { + emitDecorators(node, node.decorators); + emitModifiers(node, node.modifiers); + writeIfPresent(node.asteriskToken, "*"); + emit(node.name); + emitSignatureAndBody(node, emitSignatureHead); + } + + function emitConstructor(node: ConstructorDeclaration) { + emitModifiers(node, node.modifiers); + write("constructor"); + emitSignatureAndBody(node, emitSignatureHead); + } + + function emitAccessorDeclaration(node: AccessorDeclaration) { + emitDecorators(node, node.decorators); + emitModifiers(node, node.modifiers); + write(node.kind === SyntaxKind.GetAccessor ? "get " : "set "); + emit(node.name); + emitSignatureAndBody(node, emitSignatureHead); + } + + function emitCallSignature(node: CallSignatureDeclaration) { + emitDecorators(node, node.decorators); + emitModifiers(node, node.modifiers); + emitTypeParameters(node, node.typeParameters); + emitParameters(node, node.parameters); + emitWithPrefix(": ", node.type); + write(";"); + } + + function emitConstructSignature(node: ConstructSignatureDeclaration) { + emitDecorators(node, node.decorators); + emitModifiers(node, node.modifiers); + write("new "); + emitTypeParameters(node, node.typeParameters); + emitParameters(node, node.parameters); + emitWithPrefix(": ", node.type); + write(";"); + } + + function emitIndexSignature(node: IndexSignatureDeclaration) { + emitDecorators(node, node.decorators); + emitModifiers(node, node.modifiers); + emitParametersForIndexSignature(node, node.parameters); + emitWithPrefix(": ", node.type); + write(";"); + } + + function emitSemicolonClassElement() { + write(";"); + } + + // + // Types + // + + function emitTypePredicate(node: TypePredicateNode) { + emit(node.parameterName); + write(" is "); + emit(node.type); + } + + function emitTypeReference(node: TypeReferenceNode) { + emit(node.typeName); + emitTypeArguments(node, node.typeArguments); + } + + function emitFunctionType(node: FunctionTypeNode) { + emitTypeParameters(node, node.typeParameters); + emitParametersForArrow(node, node.parameters); + write(" => "); + emit(node.type); + } + + function emitConstructorType(node: ConstructorTypeNode) { + write("new "); + emitTypeParameters(node, node.typeParameters); + emitParametersForArrow(node, node.parameters); + write(" => "); + emit(node.type); + } + + function emitTypeQuery(node: TypeQueryNode) { + write("typeof "); + emit(node.exprName); + } + + function emitTypeLiteral(node: TypeLiteralNode) { + write("{"); + emitList(node, node.members, ListFormat.TypeLiteralMembers); + write("}"); + } + + function emitArrayType(node: ArrayTypeNode) { + emit(node.elementType); + write("[]"); + } + + function emitTupleType(node: TupleTypeNode) { + write("["); + emitList(node, node.elementTypes, ListFormat.TupleTypeElements); + write("]"); + } + + function emitUnionType(node: UnionTypeNode) { + emitList(node, node.types, ListFormat.UnionTypeConstituents); + } + + function emitIntersectionType(node: IntersectionTypeNode) { + emitList(node, node.types, ListFormat.IntersectionTypeConstituents); + } + + function emitParenthesizedType(node: ParenthesizedTypeNode) { + write("("); + emit(node.type); + write(")"); + } + + function emitThisType() { + write("this"); + } + + function emitTypeOperator(node: TypeOperatorNode) { + writeTokenText(node.operator); + write(" "); + emit(node.type); + } + + function emitIndexedAccessType(node: IndexedAccessTypeNode) { + emit(node.objectType); + write("["); + emit(node.indexType); + write("]"); + } + + function emitMappedType(node: MappedTypeNode) { + write("{"); + writeLine(); + increaseIndent(); + writeIfPresent(node.readonlyToken, "readonly "); + write("["); + emit(node.typeParameter.name); + write(" in "); + emit(node.typeParameter.constraint); + write("]"); + writeIfPresent(node.questionToken, "?"); + write(": "); + emit(node.type); + write(";"); + writeLine(); + decreaseIndent(); + write("}"); + } + + function emitLiteralType(node: LiteralTypeNode) { + emitExpression(node.literal); + } + + // + // Binding patterns + // + + function emitObjectBindingPattern(node: ObjectBindingPattern) { + const elements = node.elements; + if (elements.length === 0) { + write("{}"); + } + else { + write("{"); + emitList(node, elements, ListFormat.ObjectBindingPatternElements); + write("}"); + } + } + + function emitArrayBindingPattern(node: ArrayBindingPattern) { + const elements = node.elements; + if (elements.length === 0) { + write("[]"); + } + else { + write("["); + emitList(node, node.elements, ListFormat.ArrayBindingPatternElements); + write("]"); + } + } + + function emitBindingElement(node: BindingElement) { + emitWithSuffix(node.propertyName, ": "); + writeIfPresent(node.dotDotDotToken, "..."); + emit(node.name); + emitExpressionWithPrefix(" = ", node.initializer); + } + + // + // Expressions + // + + function emitArrayLiteralExpression(node: ArrayLiteralExpression) { + const elements = node.elements; + if (elements.length === 0) { + write("[]"); + } + else { + const preferNewLine = node.multiLine ? ListFormat.PreferNewLine : ListFormat.None; + emitExpressionList(node, elements, ListFormat.ArrayLiteralExpressionElements | preferNewLine); + } + } + + function emitObjectLiteralExpression(node: ObjectLiteralExpression) { + const properties = node.properties; + if (properties.length === 0) { + write("{}"); + } + else { + const indentedFlag = getEmitFlags(node) & EmitFlags.Indented; + if (indentedFlag) { + increaseIndent(); + } + + const preferNewLine = node.multiLine ? ListFormat.PreferNewLine : ListFormat.None; + const allowTrailingComma = languageVersion >= ScriptTarget.ES5 ? ListFormat.AllowTrailingComma : ListFormat.None; + emitList(node, properties, ListFormat.ObjectLiteralExpressionProperties | allowTrailingComma | preferNewLine); + + if (indentedFlag) { + decreaseIndent(); + } + } + } + + function emitPropertyAccessExpression(node: PropertyAccessExpression) { + let indentBeforeDot = false; + let indentAfterDot = false; + if (!(getEmitFlags(node) & EmitFlags.NoIndentation)) { + const dotRangeStart = node.expression.end; + const dotRangeEnd = skipTrivia(currentSourceFile.text, node.expression.end) + 1; + const dotToken = { kind: SyntaxKind.DotToken, pos: dotRangeStart, end: dotRangeEnd }; + indentBeforeDot = needsIndentation(node, node.expression, dotToken); + indentAfterDot = needsIndentation(node, dotToken, node.name); + } + + emitExpression(node.expression); + increaseIndentIf(indentBeforeDot); + + const shouldEmitDotDot = !indentBeforeDot && needsDotDotForPropertyAccess(node.expression); + write(shouldEmitDotDot ? ".." : "."); + + increaseIndentIf(indentAfterDot); + emit(node.name); + decreaseIndentIf(indentBeforeDot, indentAfterDot); + } + + // 1..toString is a valid property access, emit a dot after the literal + // Also emit a dot if expression is a integer const enum value - it will appear in generated code as numeric literal + function needsDotDotForPropertyAccess(expression: Expression) { + if (expression.kind === SyntaxKind.NumericLiteral) { + // check if numeric literal is a decimal literal that was originally written with a dot + const text = getLiteralTextOfNode(expression); + return getNumericLiteralFlags(text, /*hint*/ NumericLiteralFlags.All) === NumericLiteralFlags.None + && !(expression).isOctalLiteral + && text.indexOf(tokenToString(SyntaxKind.DotToken)) < 0; + } + else if (isPropertyAccessExpression(expression) || isElementAccessExpression(expression)) { + // check if constant enum value is integer + const constantValue = getConstantValue(expression); + // isFinite handles cases when constantValue is undefined + return isFinite(constantValue) + && Math.floor(constantValue) === constantValue + && compilerOptions.removeComments; + } + } + + function emitElementAccessExpression(node: ElementAccessExpression) { + emitExpression(node.expression); + write("["); + emitExpression(node.argumentExpression); + write("]"); + } + + function emitCallExpression(node: CallExpression) { + emitExpression(node.expression); + emitTypeArguments(node, node.typeArguments); + emitExpressionList(node, node.arguments, ListFormat.CallExpressionArguments); + } + + function emitNewExpression(node: NewExpression) { + write("new "); + emitExpression(node.expression); + emitTypeArguments(node, node.typeArguments); + emitExpressionList(node, node.arguments, ListFormat.NewExpressionArguments); + } + + function emitTaggedTemplateExpression(node: TaggedTemplateExpression) { + emitExpression(node.tag); + write(" "); + emitExpression(node.template); + } + + function emitTypeAssertionExpression(node: TypeAssertion) { + write("<"); + emit(node.type); + write(">"); + emitExpression(node.expression); + } + + function emitParenthesizedExpression(node: ParenthesizedExpression) { + write("("); + emitExpression(node.expression); + write(")"); + } + + function emitFunctionExpression(node: FunctionExpression) { + emitFunctionDeclarationOrExpression(node); + } + + function emitArrowFunction(node: ArrowFunction) { + emitDecorators(node, node.decorators); + emitModifiers(node, node.modifiers); + emitSignatureAndBody(node, emitArrowFunctionHead); + } + + function emitArrowFunctionHead(node: ArrowFunction) { + emitTypeParameters(node, node.typeParameters); + emitParametersForArrow(node, node.parameters); + emitWithPrefix(": ", node.type); + write(" =>"); + } + + function emitDeleteExpression(node: DeleteExpression) { + write("delete "); + emitExpression(node.expression); + } + + function emitTypeOfExpression(node: TypeOfExpression) { + write("typeof "); + emitExpression(node.expression); + } + + function emitVoidExpression(node: VoidExpression) { + write("void "); + emitExpression(node.expression); + } + + function emitAwaitExpression(node: AwaitExpression) { + write("await "); + emitExpression(node.expression); + } + + function emitPrefixUnaryExpression(node: PrefixUnaryExpression) { + writeTokenText(node.operator); + if (shouldEmitWhitespaceBeforeOperand(node)) { + write(" "); + } + emitExpression(node.operand); + } + + function shouldEmitWhitespaceBeforeOperand(node: PrefixUnaryExpression) { + // In some cases, we need to emit a space between the operator and the operand. One obvious case + // is when the operator is an identifier, like delete or typeof. We also need to do this for plus + // and minus expressions in certain cases. Specifically, consider the following two cases (parens + // are just for clarity of exposition, and not part of the source code): + // + // (+(+1)) + // (+(++1)) + // + // We need to emit a space in both cases. In the first case, the absence of a space will make + // the resulting expression a prefix increment operation. And in the second, it will make the resulting + // expression a prefix increment whose operand is a plus expression - (++(+x)) + // The same is true of minus of course. + const operand = node.operand; + return operand.kind === SyntaxKind.PrefixUnaryExpression + && ((node.operator === SyntaxKind.PlusToken && ((operand).operator === SyntaxKind.PlusToken || (operand).operator === SyntaxKind.PlusPlusToken)) + || (node.operator === SyntaxKind.MinusToken && ((operand).operator === SyntaxKind.MinusToken || (operand).operator === SyntaxKind.MinusMinusToken))); + } + + function emitPostfixUnaryExpression(node: PostfixUnaryExpression) { + emitExpression(node.operand); + writeTokenText(node.operator); + } + + function emitBinaryExpression(node: BinaryExpression) { + const isCommaOperator = node.operatorToken.kind !== SyntaxKind.CommaToken; + const indentBeforeOperator = needsIndentation(node, node.left, node.operatorToken); + const indentAfterOperator = needsIndentation(node, node.operatorToken, node.right); + + emitExpression(node.left); + increaseIndentIf(indentBeforeOperator, isCommaOperator ? " " : undefined); + writeTokenText(node.operatorToken.kind); + increaseIndentIf(indentAfterOperator, " "); + emitExpression(node.right); + decreaseIndentIf(indentBeforeOperator, indentAfterOperator); + } + + function emitConditionalExpression(node: ConditionalExpression) { + const indentBeforeQuestion = needsIndentation(node, node.condition, node.questionToken); + const indentAfterQuestion = needsIndentation(node, node.questionToken, node.whenTrue); + const indentBeforeColon = needsIndentation(node, node.whenTrue, node.colonToken); + const indentAfterColon = needsIndentation(node, node.colonToken, node.whenFalse); + + emitExpression(node.condition); + increaseIndentIf(indentBeforeQuestion, " "); + write("?"); + increaseIndentIf(indentAfterQuestion, " "); + emitExpression(node.whenTrue); + decreaseIndentIf(indentBeforeQuestion, indentAfterQuestion); + + increaseIndentIf(indentBeforeColon, " "); + write(":"); + increaseIndentIf(indentAfterColon, " "); + emitExpression(node.whenFalse); + decreaseIndentIf(indentBeforeColon, indentAfterColon); + } + + function emitTemplateExpression(node: TemplateExpression) { + emit(node.head); + emitList(node, node.templateSpans, ListFormat.TemplateExpressionSpans); + } + + function emitYieldExpression(node: YieldExpression) { + write(node.asteriskToken ? "yield*" : "yield"); + emitExpressionWithPrefix(" ", node.expression); + } + + function emitSpreadExpression(node: SpreadElement) { + write("..."); + emitExpression(node.expression); + } + + function emitClassExpression(node: ClassExpression) { + emitClassDeclarationOrExpression(node); + } + + function emitExpressionWithTypeArguments(node: ExpressionWithTypeArguments) { + emitExpression(node.expression); + emitTypeArguments(node, node.typeArguments); + } + + function emitAsExpression(node: AsExpression) { + emitExpression(node.expression); + if (node.type) { + write(" as "); + emit(node.type); + } + } + + function emitNonNullExpression(node: NonNullExpression) { + emitExpression(node.expression); + write("!"); + } + + function emitMetaProperty(node: MetaProperty) { + writeToken(node.keywordToken, node.pos); + write("."); + emit(node.name); + } + + // + // Misc + // + + function emitTemplateSpan(node: TemplateSpan) { + emitExpression(node.expression); + emit(node.literal); + } + + // + // Statements + // + + function emitBlock(node: Block) { + if (isSingleLineEmptyBlock(node)) { + writeToken(SyntaxKind.OpenBraceToken, node.pos, /*contextNode*/ node); + write(" "); + writeToken(SyntaxKind.CloseBraceToken, node.statements.end, /*contextNode*/ node); + } + else { + writeToken(SyntaxKind.OpenBraceToken, node.pos, /*contextNode*/ node); + emitBlockStatements(node); + writeToken(SyntaxKind.CloseBraceToken, node.statements.end, /*contextNode*/ node); + } + } + + function emitBlockStatements(node: BlockLike) { + if (getEmitFlags(node) & EmitFlags.SingleLine) { + emitList(node, node.statements, ListFormat.SingleLineBlockStatements); + } + else { + emitList(node, node.statements, ListFormat.MultiLineBlockStatements); + } + } + + function emitVariableStatement(node: VariableStatement) { + emitModifiers(node, node.modifiers); + emit(node.declarationList); + write(";"); + } + + function emitEmptyStatement() { + write(";"); + } + + function emitExpressionStatement(node: ExpressionStatement) { + emitExpression(node.expression); + write(";"); + } + + function emitIfStatement(node: IfStatement) { + const openParenPos = writeToken(SyntaxKind.IfKeyword, node.pos, node); + write(" "); + writeToken(SyntaxKind.OpenParenToken, openParenPos, node); + emitExpression(node.expression); + writeToken(SyntaxKind.CloseParenToken, node.expression.end, node); + emitEmbeddedStatement(node, node.thenStatement); + if (node.elseStatement) { + writeLineOrSpace(node); + writeToken(SyntaxKind.ElseKeyword, node.thenStatement.end, node); + if (node.elseStatement.kind === SyntaxKind.IfStatement) { + write(" "); + emit(node.elseStatement); + } + else { + emitEmbeddedStatement(node, node.elseStatement); + } + } + } + + function emitDoStatement(node: DoStatement) { + write("do"); + emitEmbeddedStatement(node, node.statement); + if (isBlock(node.statement)) { + write(" "); + } + else { + writeLineOrSpace(node); + } + + write("while ("); + emitExpression(node.expression); + write(");"); + } + + function emitWhileStatement(node: WhileStatement) { + write("while ("); + emitExpression(node.expression); + write(")"); + emitEmbeddedStatement(node, node.statement); + } + + function emitForStatement(node: ForStatement) { + const openParenPos = writeToken(SyntaxKind.ForKeyword, node.pos); + write(" "); + writeToken(SyntaxKind.OpenParenToken, openParenPos, /*contextNode*/ node); + emitForBinding(node.initializer); + write(";"); + emitExpressionWithPrefix(" ", node.condition); + write(";"); + emitExpressionWithPrefix(" ", node.incrementor); + write(")"); + emitEmbeddedStatement(node, node.statement); + } + + function emitForInStatement(node: ForInStatement) { + const openParenPos = writeToken(SyntaxKind.ForKeyword, node.pos); + write(" "); + writeToken(SyntaxKind.OpenParenToken, openParenPos); + emitForBinding(node.initializer); + write(" in "); + emitExpression(node.expression); + writeToken(SyntaxKind.CloseParenToken, node.expression.end); + emitEmbeddedStatement(node, node.statement); + } + + function emitForOfStatement(node: ForOfStatement) { + const openParenPos = writeToken(SyntaxKind.ForKeyword, node.pos); + write(" "); + writeToken(SyntaxKind.OpenParenToken, openParenPos); + emitForBinding(node.initializer); + write(" of "); + emitExpression(node.expression); + writeToken(SyntaxKind.CloseParenToken, node.expression.end); + emitEmbeddedStatement(node, node.statement); + } + + function emitForBinding(node: VariableDeclarationList | Expression) { + if (node !== undefined) { + if (node.kind === SyntaxKind.VariableDeclarationList) { + emit(node); + } + else { + emitExpression(node); + } + } + } + + function emitContinueStatement(node: ContinueStatement) { + writeToken(SyntaxKind.ContinueKeyword, node.pos); + emitWithPrefix(" ", node.label); + write(";"); + } + + function emitBreakStatement(node: BreakStatement) { + writeToken(SyntaxKind.BreakKeyword, node.pos); + emitWithPrefix(" ", node.label); + write(";"); + } + + function emitReturnStatement(node: ReturnStatement) { + writeToken(SyntaxKind.ReturnKeyword, node.pos, /*contextNode*/ node); + emitExpressionWithPrefix(" ", node.expression); + write(";"); + } + + function emitWithStatement(node: WithStatement) { + write("with ("); + emitExpression(node.expression); + write(")"); + emitEmbeddedStatement(node, node.statement); + } + + function emitSwitchStatement(node: SwitchStatement) { + const openParenPos = writeToken(SyntaxKind.SwitchKeyword, node.pos); + write(" "); + writeToken(SyntaxKind.OpenParenToken, openParenPos); + emitExpression(node.expression); + writeToken(SyntaxKind.CloseParenToken, node.expression.end); + write(" "); + emit(node.caseBlock); + } + + function emitLabeledStatement(node: LabeledStatement) { + emit(node.label); + write(": "); + emit(node.statement); + } + + function emitThrowStatement(node: ThrowStatement) { + write("throw"); + emitExpressionWithPrefix(" ", node.expression); + write(";"); + } + + function emitTryStatement(node: TryStatement) { + write("try "); + emit(node.tryBlock); + if (node.catchClause) { + writeLineOrSpace(node); + emit(node.catchClause); + } + if (node.finallyBlock) { + writeLineOrSpace(node); + write("finally "); + emit(node.finallyBlock); + } + } + + function emitDebuggerStatement(node: DebuggerStatement) { + writeToken(SyntaxKind.DebuggerKeyword, node.pos); + write(";"); + } + + // + // Declarations + // + + function emitVariableDeclaration(node: VariableDeclaration) { + emit(node.name); + emitWithPrefix(": ", node.type); + emitExpressionWithPrefix(" = ", node.initializer); + } + + function emitVariableDeclarationList(node: VariableDeclarationList) { + write(isLet(node) ? "let " : isConst(node) ? "const " : "var "); + emitList(node, node.declarations, ListFormat.VariableDeclarationList); + } + + function emitFunctionDeclaration(node: FunctionDeclaration) { + emitFunctionDeclarationOrExpression(node); + } + + function emitFunctionDeclarationOrExpression(node: FunctionDeclaration | FunctionExpression) { + emitDecorators(node, node.decorators); + emitModifiers(node, node.modifiers); + write(node.asteriskToken ? "function* " : "function "); + emitIdentifierName(node.name); + emitSignatureAndBody(node, emitSignatureHead); + } + + function emitSignatureAndBody(node: FunctionLikeDeclaration, emitSignatureHead: (node: SignatureDeclaration) => void) { + const body = node.body; + if (body) { + if (isBlock(body)) { + const indentedFlag = getEmitFlags(node) & EmitFlags.Indented; + if (indentedFlag) { + increaseIndent(); + } + + if (getEmitFlags(node) & EmitFlags.ReuseTempVariableScope) { + emitSignatureHead(node); + emitBlockFunctionBody(body); + } + else { + pushNameGenerationScope(); + emitSignatureHead(node); + emitBlockFunctionBody(body); + popNameGenerationScope(); + } + + if (indentedFlag) { + decreaseIndent(); + } + } + else { + emitSignatureHead(node); + write(" "); + emitExpression(body); + } + } + else { + emitSignatureHead(node); + write(";"); + } + + } + + function emitSignatureHead(node: FunctionDeclaration | FunctionExpression | MethodDeclaration | AccessorDeclaration | ConstructorDeclaration) { + emitTypeParameters(node, node.typeParameters); + emitParameters(node, node.parameters); + emitWithPrefix(": ", node.type); + } + + function shouldEmitBlockFunctionBodyOnSingleLine(body: Block) { + // We must emit a function body as a single-line body in the following case: + // * The body has NodeEmitFlags.SingleLine specified. + + // We must emit a function body as a multi-line body in the following cases: + // * The body is explicitly marked as multi-line. + // * A non-synthesized body's start and end position are on different lines. + // * Any statement in the body starts on a new line. + + if (getEmitFlags(body) & EmitFlags.SingleLine) { + return true; + } + + if (body.multiLine) { + return false; + } + + if (!nodeIsSynthesized(body) && !rangeIsOnSingleLine(body, currentSourceFile)) { + return false; + } + + if (shouldWriteLeadingLineTerminator(body, body.statements, ListFormat.PreserveLines) + || shouldWriteClosingLineTerminator(body, body.statements, ListFormat.PreserveLines)) { + return false; + } + + let previousStatement: Statement; + for (const statement of body.statements) { + if (shouldWriteSeparatingLineTerminator(previousStatement, statement, ListFormat.PreserveLines)) { + return false; + } + + previousStatement = statement; + } + + return true; + } + + function emitBlockFunctionBody(body: Block) { + write(" {"); + increaseIndent(); + + const emitBlockFunctionBody = shouldEmitBlockFunctionBodyOnSingleLine(body) + ? emitBlockFunctionBodyOnSingleLine + : emitBlockFunctionBodyWorker; + + emitBodyIndirect(body, body.statements, emitBlockFunctionBody); + + decreaseIndent(); + writeToken(SyntaxKind.CloseBraceToken, body.statements.end, body); + } + + function emitBlockFunctionBodyOnSingleLine(body: Block) { + emitBlockFunctionBodyWorker(body, /*emitBlockFunctionBodyOnSingleLine*/ true); + } + + function emitBlockFunctionBodyWorker(body: Block, emitBlockFunctionBodyOnSingleLine?: boolean) { + // Emit all the prologue directives (like "use strict"). + const statementOffset = emitPrologueDirectives(body.statements, /*startWithNewLine*/ true); + const pos = writer.getTextPos(); + emitHelpersIndirect(body); + if (statementOffset === 0 && pos === writer.getTextPos() && emitBlockFunctionBodyOnSingleLine) { + decreaseIndent(); + emitList(body, body.statements, ListFormat.SingleLineFunctionBodyStatements); + increaseIndent(); + } + else { + emitList(body, body.statements, ListFormat.MultiLineFunctionBodyStatements, statementOffset); + } + } + + function emitClassDeclaration(node: ClassDeclaration) { + emitClassDeclarationOrExpression(node); + } + + function emitClassDeclarationOrExpression(node: ClassDeclaration | ClassExpression) { + emitDecorators(node, node.decorators); + emitModifiers(node, node.modifiers); + write("class"); + emitNodeWithPrefix(" ", node.name, emitIdentifierName); + + const indentedFlag = getEmitFlags(node) & EmitFlags.Indented; + if (indentedFlag) { + increaseIndent(); + } + + emitTypeParameters(node, node.typeParameters); + emitList(node, node.heritageClauses, ListFormat.ClassHeritageClauses); + + pushNameGenerationScope(); + write(" {"); + emitList(node, node.members, ListFormat.ClassMembers); + write("}"); + popNameGenerationScope(); + + if (indentedFlag) { + decreaseIndent(); + } + } + + function emitInterfaceDeclaration(node: InterfaceDeclaration) { + emitDecorators(node, node.decorators); + emitModifiers(node, node.modifiers); + write("interface "); + emit(node.name); + emitTypeParameters(node, node.typeParameters); + emitList(node, node.heritageClauses, ListFormat.HeritageClauses); + write(" {"); + emitList(node, node.members, ListFormat.InterfaceMembers); + write("}"); + } + + function emitTypeAliasDeclaration(node: TypeAliasDeclaration) { + emitDecorators(node, node.decorators); + emitModifiers(node, node.modifiers); + write("type "); + emit(node.name); + emitTypeParameters(node, node.typeParameters); + write(" = "); + emit(node.type); + write(";"); + } + + function emitEnumDeclaration(node: EnumDeclaration) { + emitModifiers(node, node.modifiers); + write("enum "); + emit(node.name); + pushNameGenerationScope(); + write(" {"); + emitList(node, node.members, ListFormat.EnumMembers); + write("}"); + popNameGenerationScope(); + } + + function emitModuleDeclaration(node: ModuleDeclaration) { + emitModifiers(node, node.modifiers); + write(node.flags & NodeFlags.Namespace ? "namespace " : "module "); + emit(node.name); + + let body = node.body; + while (body.kind === SyntaxKind.ModuleDeclaration) { + write("."); + emit((body).name); + body = (body).body; + } + + write(" "); + emit(body); + } + + function emitModuleBlock(node: ModuleBlock) { + if (isEmptyBlock(node)) { + write("{ }"); + } + else { + pushNameGenerationScope(); + write("{"); + increaseIndent(); + emitBlockStatements(node); + write("}"); + popNameGenerationScope(); + } + } + + function emitCaseBlock(node: CaseBlock) { + writeToken(SyntaxKind.OpenBraceToken, node.pos); + emitList(node, node.clauses, ListFormat.CaseBlockClauses); + writeToken(SyntaxKind.CloseBraceToken, node.clauses.end); + } + + function emitImportEqualsDeclaration(node: ImportEqualsDeclaration) { + emitModifiers(node, node.modifiers); + write("import "); + emit(node.name); + write(" = "); + emitModuleReference(node.moduleReference); + write(";"); + } + + function emitModuleReference(node: ModuleReference) { + if (node.kind === SyntaxKind.Identifier) { + emitExpression(node); + } + else { + emit(node); + } + } + + function emitImportDeclaration(node: ImportDeclaration) { + emitModifiers(node, node.modifiers); + write("import "); + if (node.importClause) { + emit(node.importClause); + write(" from "); + } + emitExpression(node.moduleSpecifier); + write(";"); + } + + function emitImportClause(node: ImportClause) { + emit(node.name); + if (node.name && node.namedBindings) { + write(", "); + } + emit(node.namedBindings); + } + + function emitNamespaceImport(node: NamespaceImport) { + write("* as "); + emit(node.name); + } + + function emitNamedImports(node: NamedImports) { + emitNamedImportsOrExports(node); + } + + function emitImportSpecifier(node: ImportSpecifier) { + emitImportOrExportSpecifier(node); + } + + function emitExportAssignment(node: ExportAssignment) { + write(node.isExportEquals ? "export = " : "export default "); + emitExpression(node.expression); + write(";"); + } + + function emitExportDeclaration(node: ExportDeclaration) { + write("export "); + if (node.exportClause) { + emit(node.exportClause); + } + else { + write("*"); + } + if (node.moduleSpecifier) { + write(" from "); + emitExpression(node.moduleSpecifier); + } + write(";"); + } + + function emitNamedExports(node: NamedExports) { + emitNamedImportsOrExports(node); + } + + function emitExportSpecifier(node: ExportSpecifier) { + emitImportOrExportSpecifier(node); + } + + function emitNamedImportsOrExports(node: NamedImportsOrExports) { + write("{"); + emitList(node, node.elements, ListFormat.NamedImportsOrExportsElements); + write("}"); + } + + function emitImportOrExportSpecifier(node: ImportOrExportSpecifier) { + if (node.propertyName) { + emit(node.propertyName); + write(" as "); + } + + emit(node.name); + } + + // + // Module references + // + + function emitExternalModuleReference(node: ExternalModuleReference) { + write("require("); + emitExpression(node.expression); + write(")"); + } + + // + // JSX + // + + function emitJsxElement(node: JsxElement) { + emit(node.openingElement); + emitList(node, node.children, ListFormat.JsxElementChildren); + emit(node.closingElement); + } + + function emitJsxSelfClosingElement(node: JsxSelfClosingElement) { + write("<"); + emitJsxTagName(node.tagName); + write(" "); + emitList(node, node.attributes, ListFormat.JsxElementAttributes); + write("/>"); + } + + function emitJsxOpeningElement(node: JsxOpeningElement) { + write("<"); + emitJsxTagName(node.tagName); + writeIfAny(node.attributes, " "); + emitList(node, node.attributes, ListFormat.JsxElementAttributes); + write(">"); + } + + function emitJsxText(node: JsxText) { + writer.writeLiteral(getTextOfNode(node, /*includeTrivia*/ true)); + } + + function emitJsxClosingElement(node: JsxClosingElement) { + write(""); + } + + function emitJsxAttribute(node: JsxAttribute) { + emit(node.name); + emitWithPrefix("=", node.initializer); + } + + function emitJsxSpreadAttribute(node: JsxSpreadAttribute) { + write("{..."); + emitExpression(node.expression); + write("}"); + } + + function emitJsxExpression(node: JsxExpression) { + if (node.expression) { + write("{"); + if (node.dotDotDotToken) { + write("..."); + } + emitExpression(node.expression); + write("}"); + } + } + + function emitJsxTagName(node: JsxTagNameExpression) { + if (node.kind === SyntaxKind.Identifier) { + emitExpression(node); + } + else { + emit(node); + } + } + + // + // Clauses + // + + function emitCaseClause(node: CaseClause) { + write("case "); + emitExpression(node.expression); + write(":"); + + emitCaseOrDefaultClauseStatements(node, node.statements); + } + + function emitDefaultClause(node: DefaultClause) { + write("default:"); + emitCaseOrDefaultClauseStatements(node, node.statements); + } + + function emitCaseOrDefaultClauseStatements(parentNode: Node, statements: NodeArray) { + const emitAsSingleStatement = + statements.length === 1 && + ( + // treat synthesized nodes as located on the same line for emit purposes + nodeIsSynthesized(parentNode) || + nodeIsSynthesized(statements[0]) || + rangeStartPositionsAreOnSameLine(parentNode, statements[0], currentSourceFile) + ); + + if (emitAsSingleStatement) { + write(" "); + emit(statements[0]); + } + else { + emitList(parentNode, statements, ListFormat.CaseOrDefaultClauseStatements); + } + } + + function emitHeritageClause(node: HeritageClause) { + write(" "); + writeTokenText(node.token); + write(" "); + emitList(node, node.types, ListFormat.HeritageClauseTypes); + } + + function emitCatchClause(node: CatchClause) { + writeLine(); + const openParenPos = writeToken(SyntaxKind.CatchKeyword, node.pos); + write(" "); + writeToken(SyntaxKind.OpenParenToken, openParenPos); + emit(node.variableDeclaration); + writeToken(SyntaxKind.CloseParenToken, node.variableDeclaration ? node.variableDeclaration.end : openParenPos); + write(" "); + emit(node.block); + } + + // + // Property assignments + // + + function emitPropertyAssignment(node: PropertyAssignment) { + emit(node.name); + write(": "); + // This is to ensure that we emit comment in the following case: + // For example: + // obj = { + // id: /*comment1*/ ()=>void + // } + // "comment1" is not considered to be leading comment for node.initializer + // but rather a trailing comment on the previous node. + const initializer = node.initializer; + if (onEmitTrailingCommentsOfPosition && (getEmitFlags(initializer) & EmitFlags.NoLeadingComments) === 0) { + const commentRange = getCommentRange(initializer); + onEmitTrailingCommentsOfPosition(commentRange.pos); + } + emitExpression(initializer); + } + + function emitShorthandPropertyAssignment(node: ShorthandPropertyAssignment) { + emit(node.name); + if (node.objectAssignmentInitializer) { + write(" = "); + emitExpression(node.objectAssignmentInitializer); + } + } + + function emitSpreadAssignment(node: SpreadAssignment) { + if (node.expression) { + write("..."); + emitExpression(node.expression); + } + } + + // + // Enum + // + + function emitEnumMember(node: EnumMember) { + emit(node.name); + emitExpressionWithPrefix(" = ", node.initializer); + } + + // + // Top-level nodes + // + + function emitSourceFile(node: SourceFile) { + writeLine(); + emitShebang(); + emitBodyIndirect(node, node.statements, emitSourceFileWorker); + } + + function emitSourceFileWorker(node: SourceFile) { + const statements = node.statements; + const statementOffset = emitPrologueDirectives(statements); + pushNameGenerationScope(); + emitHelpersIndirect(node); + emitList(node, statements, ListFormat.MultiLine, statementOffset); + popNameGenerationScope(); + } + + // Transformation nodes + + function emitPartiallyEmittedExpression(node: PartiallyEmittedExpression) { + emitExpression(node.expression); + } + + /** + * Emits any prologue directives at the start of a Statement list, returning the + * number of prologue directives written to the output. + */ + function emitPrologueDirectives(statements: Node[], startWithNewLine?: boolean): number { + for (let i = 0; i < statements.length; i++) { + if (isPrologueDirective(statements[i])) { + if (startWithNewLine || i > 0) { + writeLine(); + } + emit(statements[i]); + } + else { + // return index of the first non prologue directive + return i; + } + } + + return statements.length; + } + + // + // Helpers + // + + function emitShebang() { + const shebang = getShebang(currentSourceFile.text); + if (shebang) { + write(shebang); + writeLine(); + } + } + + function emitModifiers(node: Node, modifiers: NodeArray) { + if (modifiers && modifiers.length) { + emitList(node, modifiers, ListFormat.Modifiers); + write(" "); + } + } + + function emitWithPrefix(prefix: string, node: Node) { + emitNodeWithPrefix(prefix, node, emit); + } + + function emitExpressionWithPrefix(prefix: string, node: Node) { + emitNodeWithPrefix(prefix, node, emitExpression); + } + + function emitNodeWithPrefix(prefix: string, node: Node, emit: (node: Node) => void) { + if (node) { + write(prefix); + emit(node); + } + } + + function emitWithSuffix(node: Node, suffix: string) { + if (node) { + emit(node); + write(suffix); + } + } + + function emitEmbeddedStatement(parent: Node, node: Statement) { + if (isBlock(node) || getEmitFlags(parent) & EmitFlags.SingleLine) { + write(" "); + emit(node); + } + else { + writeLine(); + increaseIndent(); + emit(node); + decreaseIndent(); + } + } + + function emitDecorators(parentNode: Node, decorators: NodeArray) { + emitList(parentNode, decorators, ListFormat.Decorators); + } + + function emitTypeArguments(parentNode: Node, typeArguments: NodeArray) { + emitList(parentNode, typeArguments, ListFormat.TypeArguments); + } + + function emitTypeParameters(parentNode: Node, typeParameters: NodeArray) { + emitList(parentNode, typeParameters, ListFormat.TypeParameters); + } + + function emitParameters(parentNode: Node, parameters: NodeArray) { + emitList(parentNode, parameters, ListFormat.Parameters); + } + + function emitParametersForArrow(parentNode: Node, parameters: NodeArray) { + if (parameters && + parameters.length === 1 && + parameters[0].type === undefined && + parameters[0].pos === parentNode.pos) { + emit(parameters[0]); + } + else { + emitParameters(parentNode, parameters); + } + } + + function emitParametersForIndexSignature(parentNode: Node, parameters: NodeArray) { + emitList(parentNode, parameters, ListFormat.IndexSignatureParameters); + } + + function emitList(parentNode: Node, children: NodeArray, format: ListFormat, start?: number, count?: number) { + emitNodeList(emit, parentNode, children, format, start, count); + } + + function emitExpressionList(parentNode: Node, children: NodeArray, format: ListFormat, start?: number, count?: number) { + emitNodeList(emitExpression, parentNode, children, format, start, count); + } + + function emitNodeList(emit: (node: Node) => void, parentNode: Node, children: NodeArray, format: ListFormat, start = 0, count = children ? children.length - start : 0) { + const isUndefined = children === undefined; + if (isUndefined && format & ListFormat.OptionalIfUndefined) { + return; + } + + const isEmpty = isUndefined || children.length === 0 || start >= children.length || count === 0; + if (isEmpty && format & ListFormat.OptionalIfEmpty) { + return; + } + + if (format & ListFormat.BracketsMask) { + write(getOpeningBracket(format)); + } + + if (isEmpty) { + // Write a line terminator if the parent node was multi-line + if (format & ListFormat.MultiLine) { + writeLine(); + } + else if (format & ListFormat.SpaceBetweenBraces) { + write(" "); + } + } + else { + // Write the opening line terminator or leading whitespace. + const mayEmitInterveningComments = (format & ListFormat.NoInterveningComments) === 0; + let shouldEmitInterveningComments = mayEmitInterveningComments; + if (shouldWriteLeadingLineTerminator(parentNode, children, format)) { + writeLine(); + shouldEmitInterveningComments = false; + } + else if (format & ListFormat.SpaceBetweenBraces) { + write(" "); + } + + // Increase the indent, if requested. + if (format & ListFormat.Indented) { + increaseIndent(); + } + + // Emit each child. + let previousSibling: Node; + let shouldDecreaseIndentAfterEmit: boolean; + const delimiter = getDelimiter(format); + for (let i = 0; i < count; i++) { + const child = children[start + i]; + + // Write the delimiter if this is not the first node. + if (previousSibling) { + write(delimiter); + + // Write either a line terminator or whitespace to separate the elements. + if (shouldWriteSeparatingLineTerminator(previousSibling, child, format)) { + // If a synthesized node in a single-line list starts on a new + // line, we should increase the indent. + if ((format & (ListFormat.LinesMask | ListFormat.Indented)) === ListFormat.SingleLine) { + increaseIndent(); + shouldDecreaseIndentAfterEmit = true; + } + + writeLine(); + shouldEmitInterveningComments = false; + } + else if (previousSibling && format & ListFormat.SpaceBetweenSiblings) { + write(" "); + } + } + + // Emit this child. + if (shouldEmitInterveningComments) { + if (onEmitTrailingCommentsOfPosition) { + const commentRange = getCommentRange(child); + onEmitTrailingCommentsOfPosition(commentRange.pos); + } + } + else { + shouldEmitInterveningComments = mayEmitInterveningComments; + } + + emit(child); + + if (shouldDecreaseIndentAfterEmit) { + decreaseIndent(); + shouldDecreaseIndentAfterEmit = false; + } + + previousSibling = child; + } + + // Write a trailing comma, if requested. + const hasTrailingComma = (format & ListFormat.AllowTrailingComma) && children.hasTrailingComma; + if (format & ListFormat.CommaDelimited && hasTrailingComma) { + write(","); + } + + // Decrease the indent, if requested. + if (format & ListFormat.Indented) { + decreaseIndent(); + } + + // Write the closing line terminator or closing whitespace. + if (shouldWriteClosingLineTerminator(parentNode, children, format)) { + writeLine(); + } + else if (format & ListFormat.SpaceBetweenBraces) { + write(" "); + } + } + + if (format & ListFormat.BracketsMask) { + write(getClosingBracket(format)); + } + } + + function writeIfAny(nodes: NodeArray, text: string) { + if (some(nodes)) { + write(text); + } + } + + function writeIfPresent(node: Node, text: string) { + if (node) { + write(text); + } + } + + function writeToken(token: SyntaxKind, pos: number, contextNode?: Node) { + return onEmitSourceMapOfToken + ? onEmitSourceMapOfToken(contextNode, token, pos, writeTokenText) + : writeTokenText(token, pos); + } + + function writeTokenText(token: SyntaxKind, pos?: number) { + const tokenString = tokenToString(token); + write(tokenString); + return pos < 0 ? pos : pos + tokenString.length; + } + + function writeLineOrSpace(node: Node) { + if (getEmitFlags(node) & EmitFlags.SingleLine) { + write(" "); + } + else { + writeLine(); + } + } + + function writeLines(text: string): void { + const lines = text.split(/\r\n?|\n/g); + const indentation = guessIndentation(lines); + for (let i = 0; i < lines.length; i++) { + const line = indentation ? lines[i].slice(indentation) : lines[i]; + if (line.length) { + writeLine(); + write(line); + writeLine(); + } + } + } + + function guessIndentation(lines: string[]) { + let indentation: number; + for (const line of lines) { + for (let i = 0; i < line.length && (indentation === undefined || i < indentation); i++) { + if (!isWhiteSpace(line.charCodeAt(i))) { + if (indentation === undefined || i < indentation) { + indentation = i; + break; + } + } + } + } + return indentation; + } + + function increaseIndentIf(value: boolean, valueToWriteWhenNotIndenting?: string) { + if (value) { + increaseIndent(); + writeLine(); + } + else if (valueToWriteWhenNotIndenting) { + write(valueToWriteWhenNotIndenting); + } + } + + // Helper function to decrease the indent if we previously indented. Allows multiple + // previous indent values to be considered at a time. This also allows caller to just + // call this once, passing in all their appropriate indent values, instead of needing + // to call this helper function multiple times. + function decreaseIndentIf(value1: boolean, value2?: boolean) { + if (value1) { + decreaseIndent(); + } + if (value2) { + decreaseIndent(); + } + } + + function shouldWriteLeadingLineTerminator(parentNode: Node, children: NodeArray, format: ListFormat) { + if (format & ListFormat.MultiLine) { + return true; + } + + if (format & ListFormat.PreserveLines) { + if (format & ListFormat.PreferNewLine) { + return true; + } + + const firstChild = children[0]; + if (firstChild === undefined) { + return !rangeIsOnSingleLine(parentNode, currentSourceFile); + } + else if (positionIsSynthesized(parentNode.pos) || nodeIsSynthesized(firstChild)) { + return synthesizedNodeStartsOnNewLine(firstChild, format); + } + else { + return !rangeStartPositionsAreOnSameLine(parentNode, firstChild, currentSourceFile); + } + } + else { + return false; + } + } + + function shouldWriteSeparatingLineTerminator(previousNode: Node, nextNode: Node, format: ListFormat) { + if (format & ListFormat.MultiLine) { + return true; + } + else if (format & ListFormat.PreserveLines) { + if (previousNode === undefined || nextNode === undefined) { + return false; + } + else if (nodeIsSynthesized(previousNode) || nodeIsSynthesized(nextNode)) { + return synthesizedNodeStartsOnNewLine(previousNode, format) || synthesizedNodeStartsOnNewLine(nextNode, format); + } + else { + return !rangeEndIsOnSameLineAsRangeStart(previousNode, nextNode, currentSourceFile); + } + } + else { + return nextNode.startsOnNewLine; + } + } + + function shouldWriteClosingLineTerminator(parentNode: Node, children: NodeArray, format: ListFormat) { + if (format & ListFormat.MultiLine) { + return (format & ListFormat.NoTrailingNewLine) === 0; + } + else if (format & ListFormat.PreserveLines) { + if (format & ListFormat.PreferNewLine) { + return true; + } + + const lastChild = lastOrUndefined(children); + if (lastChild === undefined) { + return !rangeIsOnSingleLine(parentNode, currentSourceFile); + } + else if (positionIsSynthesized(parentNode.pos) || nodeIsSynthesized(lastChild)) { + return synthesizedNodeStartsOnNewLine(lastChild, format); + } + else { + return !rangeEndPositionsAreOnSameLine(parentNode, lastChild, currentSourceFile); + } + } + else { + return false; + } + } + + function synthesizedNodeStartsOnNewLine(node: Node, format?: ListFormat) { + if (nodeIsSynthesized(node)) { + const startsOnNewLine = node.startsOnNewLine; + if (startsOnNewLine === undefined) { + return (format & ListFormat.PreferNewLine) !== 0; + } + + return startsOnNewLine; + } + + return (format & ListFormat.PreferNewLine) !== 0; + } + + function needsIndentation(parent: Node, node1: Node, node2: Node): boolean { + parent = skipSynthesizedParentheses(parent); + node1 = skipSynthesizedParentheses(node1); + node2 = skipSynthesizedParentheses(node2); + + // Always use a newline for synthesized code if the synthesizer desires it. + if (node2.startsOnNewLine) { + return true; + } + + return !nodeIsSynthesized(parent) + && !nodeIsSynthesized(node1) + && !nodeIsSynthesized(node2) + && !rangeEndIsOnSameLineAsRangeStart(node1, node2, currentSourceFile); + } + + function isSingleLineEmptyBlock(block: Block) { + return !block.multiLine + && isEmptyBlock(block); + } + + function isEmptyBlock(block: BlockLike) { + return block.statements.length === 0 + && rangeEndIsOnSameLineAsRangeStart(block, block, currentSourceFile); + } + + function skipSynthesizedParentheses(node: Node) { + while (node.kind === SyntaxKind.ParenthesizedExpression && nodeIsSynthesized(node)) { + node = (node).expression; + } + + return node; + } + + function getTextOfNode(node: Node, includeTrivia?: boolean): string { + if (isGeneratedIdentifier(node)) { + return generateName(node); + } + else if (isIdentifier(node) && (nodeIsSynthesized(node) || !node.parent)) { + return unescapeIdentifier(node.text); + } + else if (node.kind === SyntaxKind.StringLiteral && (node).textSourceNode) { + return getTextOfNode((node).textSourceNode, includeTrivia); + } + else if (isLiteralExpression(node) && (nodeIsSynthesized(node) || !node.parent)) { + return node.text; + } + + return getSourceTextOfNodeFromSourceFile(currentSourceFile, node, includeTrivia); + } + + function getLiteralTextOfNode(node: LiteralLikeNode): string { + if (node.kind === SyntaxKind.StringLiteral && (node).textSourceNode) { + const textSourceNode = (node).textSourceNode; + if (isIdentifier(textSourceNode)) { + return "\"" + escapeNonAsciiCharacters(escapeString(getTextOfNode(textSourceNode))) + "\""; + } + else { + return getLiteralTextOfNode(textSourceNode); + } + } + + return getLiteralText(node, currentSourceFile, languageVersion); + } + + function resetGeneratedNames() { + nodeIdToGeneratedName = undefined; + autoGeneratedIdToGeneratedName = undefined; + generatedNames = undefined; + tempFlagsStack = undefined; + tempFlags = TempFlags.Auto; + } + + function ensureNameGeneration() { + if (generatedNames === undefined) { + nodeIdToGeneratedName = []; + autoGeneratedIdToGeneratedName = []; + generatedNames = createMap(); + tempFlagsStack = []; + } + } + + /** + * Push a new name generation scope. + */ + function pushNameGenerationScope() { + ensureNameGeneration(); + tempFlagsStack.push(tempFlags); + tempFlags = 0; + } + + /** + * Pop the current name generation scope. + */ + function popNameGenerationScope() { + ensureNameGeneration(); + tempFlags = tempFlagsStack.pop(); + } + + /** + * Generate the text for a generated identifier. + */ + function generateName(name: GeneratedIdentifier) { + ensureNameGeneration(); + if (name.autoGenerateKind === GeneratedIdentifierKind.Node) { + // Node names generate unique names based on their original node + // and are cached based on that node's id. + const node = getNodeForGeneratedName(name); + return generateNameCached(node, getTextOfNode); + } + else { + // Auto, Loop, and Unique names are cached based on their unique + // autoGenerateId. + const autoGenerateId = name.autoGenerateId; + return autoGeneratedIdToGeneratedName[autoGenerateId] || (autoGeneratedIdToGeneratedName[autoGenerateId] = unescapeIdentifier(makeName(name))); + } + } + + function generateNameCached(node: Node, getTextOfNode: (node: Node, includeTrivia?: boolean) => string) { + const nodeId = getNodeId(node); + return nodeIdToGeneratedName[nodeId] || (nodeIdToGeneratedName[nodeId] = unescapeIdentifier(generateNameForNode(node, getTextOfNode))); + } + + /** + * Returns a value indicating whether a name is unique globally, within the current file, + * or within the NameGenerator. + */ + function isUniqueName(name: string): boolean { + return !(hasGlobalName && hasGlobalName(name)) + && !currentSourceFile.identifiers.has(name) + && !generatedNames.has(name); + } + + /** + * Returns a value indicating whether a name is unique within a container. + */ + function isUniqueLocalName(name: string, container: Node): boolean { + for (let node = container; isNodeDescendantOf(node, container); node = node.nextContainer) { + if (node.locals) { + const local = node.locals.get(name); + // We conservatively include alias symbols to cover cases where they're emitted as locals + if (local && local.flags & (SymbolFlags.Value | SymbolFlags.ExportValue | SymbolFlags.Alias)) { + return false; + } + } + } + return true; + } + + /** + * Return the next available name in the pattern _a ... _z, _0, _1, ... + * TempFlags._i or TempFlags._n may be used to express a preference for that dedicated name. + * Note that names generated by makeTempVariableName and makeUniqueName will never conflict. + */ + function makeTempVariableName(flags: TempFlags): string { + if (flags && !(tempFlags & flags)) { + const name = flags === TempFlags._i ? "_i" : "_n"; + if (isUniqueName(name)) { + tempFlags |= flags; + return name; + } + } + while (true) { + const count = tempFlags & TempFlags.CountMask; + tempFlags++; + // Skip over 'i' and 'n' + if (count !== 8 && count !== 13) { + const name = count < 26 + ? "_" + String.fromCharCode(CharacterCodes.a + count) + : "_" + (count - 26); + if (isUniqueName(name)) { + return name; + } + } + } + } + + /** + * Generate a name that is unique within the current file and doesn't conflict with any names + * in global scope. The name is formed by adding an '_n' suffix to the specified base name, + * where n is a positive integer. Note that names generated by makeTempVariableName and + * makeUniqueName are guaranteed to never conflict. + */ + function makeUniqueName(baseName: string): string { + // Find the first unique 'name_n', where n is a positive number + if (baseName.charCodeAt(baseName.length - 1) !== CharacterCodes._) { + baseName += "_"; + } + let i = 1; + while (true) { + const generatedName = baseName + i; + if (isUniqueName(generatedName)) { + generatedNames.set(generatedName, generatedName); + return generatedName; + } + i++; + } + } + + /** + * Generates a unique name for a ModuleDeclaration or EnumDeclaration. + */ + function generateNameForModuleOrEnum(node: ModuleDeclaration | EnumDeclaration, getTextOfNode: (node: Node, includeTrivia?: boolean) => string) { + const name = getTextOfNode(node.name); + // Use module/enum name itself if it is unique, otherwise make a unique variation + return isUniqueLocalName(name, node) ? name : makeUniqueName(name); + } + + /** + * Generates a unique name for an ImportDeclaration or ExportDeclaration. + */ + function generateNameForImportOrExportDeclaration(node: ImportDeclaration | ExportDeclaration) { + const expr = getExternalModuleName(node); + const baseName = expr.kind === SyntaxKind.StringLiteral ? + escapeIdentifier(makeIdentifierFromModuleName((expr).text)) : "module"; + return makeUniqueName(baseName); + } + + /** + * Generates a unique name for a default export. + */ + function generateNameForExportDefault() { + return makeUniqueName("default"); + } + + /** + * Generates a unique name for a class expression. + */ + function generateNameForClassExpression() { + return makeUniqueName("class"); + } + + function generateNameForMethodOrAccessor(node: MethodDeclaration | AccessorDeclaration, getTextOfNode: (node: Node, includeTrivia?: boolean) => string) { + if (isIdentifier(node.name)) { + return generateNameCached(node.name, getTextOfNode); + } + return makeTempVariableName(TempFlags.Auto); + } + + /** + * Generates a unique name from a node. + */ + function generateNameForNode(node: Node, getTextOfNode: (node: Node, includeTrivia?: boolean) => string): string { + switch (node.kind) { + case SyntaxKind.Identifier: + return makeUniqueName(getTextOfNode(node)); + case SyntaxKind.ModuleDeclaration: + case SyntaxKind.EnumDeclaration: + return generateNameForModuleOrEnum(node, getTextOfNode); + case SyntaxKind.ImportDeclaration: + case SyntaxKind.ExportDeclaration: + return generateNameForImportOrExportDeclaration(node); + case SyntaxKind.FunctionDeclaration: + case SyntaxKind.ClassDeclaration: + case SyntaxKind.ExportAssignment: + return generateNameForExportDefault(); + case SyntaxKind.ClassExpression: + return generateNameForClassExpression(); + case SyntaxKind.MethodDeclaration: + case SyntaxKind.GetAccessor: + case SyntaxKind.SetAccessor: + return generateNameForMethodOrAccessor(node, getTextOfNode); + default: + return makeTempVariableName(TempFlags.Auto); + } + } + + /** + * Generates a unique identifier for a node. + */ + function makeName(name: GeneratedIdentifier) { + switch (name.autoGenerateKind) { + case GeneratedIdentifierKind.Auto: + return makeTempVariableName(TempFlags.Auto); + case GeneratedIdentifierKind.Loop: + return makeTempVariableName(TempFlags._i); + case GeneratedIdentifierKind.Unique: + return makeUniqueName(name.text); + } + + Debug.fail("Unsupported GeneratedIdentifierKind."); + } + + /** + * Gets the node from which a name should be generated. + */ + function getNodeForGeneratedName(name: GeneratedIdentifier) { + const autoGenerateId = name.autoGenerateId; + let node = name as Node; + let original = node.original; + while (original) { + node = original; + + // if "node" is a different generated name (having a different + // "autoGenerateId"), use it and stop traversing. + if (isIdentifier(node) + && node.autoGenerateKind === GeneratedIdentifierKind.Node + && node.autoGenerateId !== autoGenerateId) { + break; + } + + original = node.original; + } + + // otherwise, return the original node for the source; + return node; + } + } + + function createDelimiterMap() { + const delimiters: string[] = []; + delimiters[ListFormat.None] = ""; + delimiters[ListFormat.CommaDelimited] = ","; + delimiters[ListFormat.BarDelimited] = " |"; + delimiters[ListFormat.AmpersandDelimited] = " &"; + return delimiters; + } + + function getDelimiter(format: ListFormat) { + return delimiters[format & ListFormat.DelimitersMask]; + } + + function createBracketsMap() { + const brackets: string[][] = []; + brackets[ListFormat.Braces] = ["{", "}"]; + brackets[ListFormat.Parenthesis] = ["(", ")"]; + brackets[ListFormat.AngleBrackets] = ["<", ">"]; + brackets[ListFormat.SquareBrackets] = ["[", "]"]; + return brackets; + } + + function getOpeningBracket(format: ListFormat) { + return brackets[format & ListFormat.BracketsMask][0]; + } + + function getClosingBracket(format: ListFormat) { + return brackets[format & ListFormat.BracketsMask][1]; + } + + const enum ListFormat { + None = 0, + + // Line separators + SingleLine = 0, // Prints the list on a single line (default). + MultiLine = 1 << 0, // Prints the list on multiple lines. + PreserveLines = 1 << 1, // Prints the list using line preservation if possible. + LinesMask = SingleLine | MultiLine | PreserveLines, + + // Delimiters + NotDelimited = 0, // There is no delimiter between list items (default). + BarDelimited = 1 << 2, // Each list item is space-and-bar (" |") delimited. + AmpersandDelimited = 1 << 3, // Each list item is space-and-ampersand (" &") delimited. + CommaDelimited = 1 << 4, // Each list item is comma (",") delimited. + DelimitersMask = BarDelimited | AmpersandDelimited | CommaDelimited, + + AllowTrailingComma = 1 << 5, // Write a trailing comma (",") if present. + + // Whitespace + Indented = 1 << 6, // The list should be indented. + SpaceBetweenBraces = 1 << 7, // Inserts a space after the opening brace and before the closing brace. + SpaceBetweenSiblings = 1 << 8, // Inserts a space between each sibling node. + + // Brackets/Braces + Braces = 1 << 9, // The list is surrounded by "{" and "}". + Parenthesis = 1 << 10, // The list is surrounded by "(" and ")". + AngleBrackets = 1 << 11, // The list is surrounded by "<" and ">". + SquareBrackets = 1 << 12, // The list is surrounded by "[" and "]". + BracketsMask = Braces | Parenthesis | AngleBrackets | SquareBrackets, + + OptionalIfUndefined = 1 << 13, // Do not emit brackets if the list is undefined. + OptionalIfEmpty = 1 << 14, // Do not emit brackets if the list is empty. + Optional = OptionalIfUndefined | OptionalIfEmpty, + + // Other + PreferNewLine = 1 << 15, // Prefer adding a LineTerminator between synthesized nodes. + NoTrailingNewLine = 1 << 16, // Do not emit a trailing NewLine for a MultiLine list. + NoInterveningComments = 1 << 17, // Do not emit comments between each node + + // Precomputed Formats + Modifiers = SingleLine | SpaceBetweenSiblings, + HeritageClauses = SingleLine | SpaceBetweenSiblings, + TypeLiteralMembers = MultiLine | Indented, + TupleTypeElements = CommaDelimited | SpaceBetweenSiblings | SingleLine | Indented, + UnionTypeConstituents = BarDelimited | SpaceBetweenSiblings | SingleLine, + IntersectionTypeConstituents = AmpersandDelimited | SpaceBetweenSiblings | SingleLine, + ObjectBindingPatternElements = SingleLine | AllowTrailingComma | SpaceBetweenBraces | CommaDelimited | SpaceBetweenSiblings, + ArrayBindingPatternElements = SingleLine | AllowTrailingComma | CommaDelimited | SpaceBetweenSiblings, + ObjectLiteralExpressionProperties = PreserveLines | CommaDelimited | SpaceBetweenSiblings | SpaceBetweenBraces | Indented | Braces, + ArrayLiteralExpressionElements = PreserveLines | CommaDelimited | SpaceBetweenSiblings | AllowTrailingComma | Indented | SquareBrackets, + CallExpressionArguments = CommaDelimited | SpaceBetweenSiblings | SingleLine | Parenthesis, + NewExpressionArguments = CommaDelimited | SpaceBetweenSiblings | SingleLine | Parenthesis | OptionalIfUndefined, + TemplateExpressionSpans = SingleLine | NoInterveningComments, + SingleLineBlockStatements = SpaceBetweenBraces | SpaceBetweenSiblings | SingleLine, + MultiLineBlockStatements = Indented | MultiLine, + VariableDeclarationList = CommaDelimited | SpaceBetweenSiblings | SingleLine, + SingleLineFunctionBodyStatements = SingleLine | SpaceBetweenSiblings | SpaceBetweenBraces, + MultiLineFunctionBodyStatements = MultiLine, + ClassHeritageClauses = SingleLine | SpaceBetweenSiblings, + ClassMembers = Indented | MultiLine, + InterfaceMembers = Indented | MultiLine, + EnumMembers = CommaDelimited | Indented | MultiLine, + CaseBlockClauses = Indented | MultiLine, + NamedImportsOrExportsElements = CommaDelimited | SpaceBetweenSiblings | AllowTrailingComma | SingleLine | SpaceBetweenBraces, + JsxElementChildren = SingleLine | NoInterveningComments, + JsxElementAttributes = SingleLine | SpaceBetweenSiblings | NoInterveningComments, + CaseOrDefaultClauseStatements = Indented | MultiLine | NoTrailingNewLine | OptionalIfEmpty, + HeritageClauseTypes = CommaDelimited | SpaceBetweenSiblings | SingleLine, + SourceFileStatements = MultiLine | NoTrailingNewLine, + Decorators = MultiLine | Optional, + TypeArguments = CommaDelimited | SpaceBetweenSiblings | SingleLine | Indented | AngleBrackets | Optional, + TypeParameters = CommaDelimited | SpaceBetweenSiblings | SingleLine | Indented | AngleBrackets | Optional, + Parameters = CommaDelimited | SpaceBetweenSiblings | SingleLine | Indented | Parenthesis, + IndexSignatureParameters = CommaDelimited | SpaceBetweenSiblings | SingleLine | Indented | SquareBrackets, + } +} \ No newline at end of file diff --git a/src/compiler/sourcemap.ts b/src/compiler/sourcemap.ts index 650b9b0ef02..d743f488e75 100644 --- a/src/compiler/sourcemap.ts +++ b/src/compiler/sourcemap.ts @@ -8,10 +8,9 @@ namespace ts { * * @param filePath The path to the generated output file. * @param sourceMapFilePath The path to the output source map file. - * @param sourceFiles The input source files for the program. - * @param isBundledEmit A value indicating whether the generated output file is a bundle. + * @param sourceFileOrBundle The input source file or bundle for the program. */ - initialize(filePath: string, sourceMapFilePath: string, sourceFiles: SourceFile[], isBundledEmit: boolean): void; + initialize(filePath: string, sourceMapFilePath: string, sourceFileOrBundle: SourceFile | Bundle): void; /** * Reset the SourceMapWriter to an empty state. @@ -38,11 +37,11 @@ namespace ts { /** * Emits a node with possible leading and trailing source maps. * - * @param emitContext The current emit context + * @param hint The current emit context * @param node The node to emit. * @param emitCallback The callback used to emit the node. */ - emitNodeWithSourceMap(emitContext: EmitContext, node: Node, emitCallback: (emitContext: EmitContext, node: Node) => void): void; + emitNodeWithSourceMap(hint: EmitHint, node: Node, emitCallback: (hint: EmitHint, node: Node) => void): void; /** * Emits a token of a node node with possible leading and trailing source maps. @@ -115,10 +114,9 @@ namespace ts { * * @param filePath The path to the generated output file. * @param sourceMapFilePath The path to the output source map file. - * @param sourceFiles The input source files for the program. - * @param isBundledEmit A value indicating whether the generated output file is a bundle. + * @param sourceFileOrBundle The input source file or bundle for the program. */ - function initialize(filePath: string, sourceMapFilePath: string, sourceFiles: SourceFile[], isBundledEmit: boolean) { + function initialize(filePath: string, sourceMapFilePath: string, sourceFileOrBundle: SourceFile | Bundle) { if (disabled) { return; } @@ -161,11 +159,10 @@ namespace ts { if (compilerOptions.mapRoot) { sourceMapDir = normalizeSlashes(compilerOptions.mapRoot); - if (!isBundledEmit) { // emitting single module file - Debug.assert(sourceFiles.length === 1); + if (sourceFileOrBundle.kind === SyntaxKind.SourceFile) { // emitting single module file // For modules or multiple emit files the mapRoot will have directory structure like the sources // So if src\a.ts and src\lib\b.ts are compiled together user would be moving the maps into mapRoot\a.js.map and mapRoot\lib\b.js.map - sourceMapDir = getDirectoryPath(getSourceFilePathInNewDir(sourceFiles[0], host, sourceMapDir)); + sourceMapDir = getDirectoryPath(getSourceFilePathInNewDir(sourceFileOrBundle, host, sourceMapDir)); } if (!isRootedDiskPath(sourceMapDir) && !isUrl(sourceMapDir)) { @@ -311,12 +308,13 @@ namespace ts { /** * Emits a node with possible leading and trailing source maps. * + * @param hint A hint as to the intended usage of the node. * @param node The node to emit. * @param emitCallback The callback used to emit the node. */ - function emitNodeWithSourceMap(emitContext: EmitContext, node: Node, emitCallback: (emitContext: EmitContext, node: Node) => void) { + function emitNodeWithSourceMap(hint: EmitHint, node: Node, emitCallback: (hint: EmitHint, node: Node) => void) { if (disabled) { - return emitCallback(emitContext, node); + return emitCallback(hint, node); } if (node) { @@ -332,11 +330,11 @@ namespace ts { if (emitFlags & EmitFlags.NoNestedSourceMaps) { disabled = true; - emitCallback(emitContext, node); + emitCallback(hint, node); disabled = false; } else { - emitCallback(emitContext, node); + emitCallback(hint, node); } if (node.kind !== SyntaxKind.NotEmittedStatement diff --git a/src/compiler/transformer.ts b/src/compiler/transformer.ts index cef8c701455..62469df79c1 100644 --- a/src/compiler/transformer.ts +++ b/src/compiler/transformer.ts @@ -105,14 +105,16 @@ namespace ts { hoistFunctionDeclaration, requestEmitHelper, readEmitHelpers, - onSubstituteNode: (_emitContext, node) => node, + onSubstituteNode: (_, node) => node, enableSubstitution, isSubstitutionEnabled, - onEmitNode: (node, emitContext, emitCallback) => emitCallback(node, emitContext), + onEmitNode: (hint, node, callback) => callback(hint, node), enableEmitNotification, isEmitNotificationEnabled }; + performance.mark("beforeTransform"); + // Chain together and initialize each transformer. const transformation = chain(...transformers)(context); @@ -122,6 +124,9 @@ namespace ts { // Disable modification of the lexical environment. lexicalEnvironmentDisabled = true; + performance.mark("afterTransform"); + performance.measure("transformTime", "beforeTransform", "afterTransform"); + return { transformed, emitNodeWithSubstitution, @@ -159,21 +164,16 @@ namespace ts { /** * Emits a node with possible substitution. * - * @param emitContext The current emit context. + * @param hint A hint as to the intended usage of the node. * @param node The node to emit. * @param emitCallback The callback used to emit the node or its substitute. */ - function emitNodeWithSubstitution(emitContext: EmitContext, node: Node, emitCallback: (emitContext: EmitContext, node: Node) => void) { + function emitNodeWithSubstitution(hint: EmitHint, node: Node, emitCallback: (hint: EmitHint, node: Node) => void) { if (node) { if (isSubstitutionEnabled(node)) { - const substitute = context.onSubstituteNode(emitContext, node); - if (substitute && substitute !== node) { - emitCallback(emitContext, substitute); - return; - } + node = context.onSubstituteNode(hint, node) || node; } - - emitCallback(emitContext, node); + emitCallback(hint, node); } } @@ -196,17 +196,17 @@ namespace ts { /** * Emits a node with possible emit notification. * - * @param emitContext The current emit context. + * @param hint A hint as to the intended usage of the node. * @param node The node to emit. * @param emitCallback The callback used to emit the node. */ - function emitNodeWithNotification(emitContext: EmitContext, node: Node, emitCallback: (emitContext: EmitContext, node: Node) => void) { + function emitNodeWithNotification(hint: EmitHint, node: Node, emitCallback: (hint: EmitHint, node: Node) => void) { if (node) { if (isEmitNotificationEnabled(node)) { - context.onEmitNode(emitContext, node, emitCallback); + context.onEmitNode(hint, node, emitCallback); } else { - emitCallback(emitContext, node); + emitCallback(hint, node); } } } diff --git a/src/compiler/transformers/es2015.ts b/src/compiler/transformers/es2015.ts index 3b8b4524aab..10ebe648fe2 100644 --- a/src/compiler/transformers/es2015.ts +++ b/src/compiler/transformers/es2015.ts @@ -3435,9 +3435,11 @@ namespace ts { /** * Called by the printer just before a node is printed. * + * @param hint A hint as to the intended usage of the node. * @param node The node to be printed. + * @param emitCallback The callback used to emit the node. */ - function onEmitNode(emitContext: EmitContext, node: Node, emitCallback: (emitContext: EmitContext, node: Node) => void) { + function onEmitNode(hint: EmitHint, node: Node, emitCallback: (hint: EmitHint, node: Node) => void) { if (enabledSubstitutions & ES2015SubstitutionFlags.CapturedThis && isFunctionLike(node)) { // If we are tracking a captured `this`, keep track of the enclosing function. const ancestorFacts = enterSubtree( @@ -3445,11 +3447,11 @@ namespace ts { getEmitFlags(node) & EmitFlags.CapturesThis ? HierarchyFacts.FunctionIncludes | HierarchyFacts.CapturesThis : HierarchyFacts.FunctionIncludes); - previousOnEmitNode(emitContext, node, emitCallback); + previousOnEmitNode(hint, node, emitCallback); exitSubtree(ancestorFacts, HierarchyFacts.None, HierarchyFacts.None); return; } - previousOnEmitNode(emitContext, node, emitCallback); + previousOnEmitNode(hint, node, emitCallback); } /** @@ -3484,13 +3486,13 @@ namespace ts { /** * Hooks node substitutions. * - * @param emitContext The context for the emitter. + * @param hint The context for the emitter. * @param node The node to substitute. */ - function onSubstituteNode(emitContext: EmitContext, node: Node) { - node = previousOnSubstituteNode(emitContext, node); + function onSubstituteNode(hint: EmitHint, node: Node) { + node = previousOnSubstituteNode(hint, node); - if (emitContext === EmitContext.Expression) { + if (hint === EmitHint.Expression) { return substituteExpression(node); } diff --git a/src/compiler/transformers/es2017.ts b/src/compiler/transformers/es2017.ts index c87dbe32518..a7f7b0da0ea 100644 --- a/src/compiler/transformers/es2017.ts +++ b/src/compiler/transformers/es2017.ts @@ -396,33 +396,33 @@ namespace ts { /** * Hook for node emit. * + * @param hint A hint as to the intended usage of the node. * @param node The node to emit. * @param emit A callback used to emit the node in the printer. */ - function onEmitNode(emitContext: EmitContext, node: Node, emitCallback: (emitContext: EmitContext, node: Node) => void): void { + function onEmitNode(hint: EmitHint, node: Node, emitCallback: (hint: EmitHint, node: Node) => void): void { // If we need to support substitutions for `super` in an async method, // we should track it here. if (enabledSubstitutions & ES2017SubstitutionFlags.AsyncMethodsWithSuper && isSuperContainer(node)) { const savedCurrentSuperContainer = currentSuperContainer; currentSuperContainer = node; - previousOnEmitNode(emitContext, node, emitCallback); + previousOnEmitNode(hint, node, emitCallback); currentSuperContainer = savedCurrentSuperContainer; } else { - previousOnEmitNode(emitContext, node, emitCallback); + previousOnEmitNode(hint, node, emitCallback); } } /** * Hooks node substitutions. * + * @param hint A hint as to the intended usage of the node. * @param node The node to substitute. - * @param isExpression A value indicating whether the node is to be used in an expression - * position. */ - function onSubstituteNode(emitContext: EmitContext, node: Node) { - node = previousOnSubstituteNode(emitContext, node); - if (emitContext === EmitContext.Expression) { + function onSubstituteNode(hint: EmitHint, node: Node) { + node = previousOnSubstituteNode(hint, node); + if (hint === EmitHint.Expression) { return substituteExpression(node); } diff --git a/src/compiler/transformers/es5.ts b/src/compiler/transformers/es5.ts index c3b011fe36d..8b030642a89 100644 --- a/src/compiler/transformers/es5.ts +++ b/src/compiler/transformers/es5.ts @@ -12,7 +12,7 @@ namespace ts { const compilerOptions = context.getCompilerOptions(); // enable emit notification only if using --jsx preserve or react-native - let previousOnEmitNode: (emitContext: EmitContext, node: Node, emitCallback: (emitContext: EmitContext, node: Node) => void) => void; + let previousOnEmitNode: (hint: EmitHint, node: Node, emitCallback: (hint: EmitHint, node: Node) => void) => void; let noSubstitution: boolean[]; if (compilerOptions.jsx === JsxEmit.Preserve || compilerOptions.jsx === JsxEmit.ReactNative) { previousOnEmitNode = context.onEmitNode; @@ -41,9 +41,11 @@ namespace ts { /** * Called by the printer just before a node is printed. * - * @param node The node to be printed. + * @param hint A hint as to the intended usage of the node. + * @param node The node to emit. + * @param emitCallback A callback used to emit the node. */ - function onEmitNode(emitContext: EmitContext, node: Node, emitCallback: (emitContext: EmitContext, node: Node) => void) { + function onEmitNode(hint: EmitHint, node: Node, emitCallback: (emitContext: EmitHint, node: Node) => void) { switch (node.kind) { case SyntaxKind.JsxOpeningElement: case SyntaxKind.JsxClosingElement: @@ -53,21 +55,21 @@ namespace ts { break; } - previousOnEmitNode(emitContext, node, emitCallback); + previousOnEmitNode(hint, node, emitCallback); } /** * Hooks node substitutions. * - * @param emitContext The context for the emitter. + * @param hint A hint as to the intended usage of the node. * @param node The node to substitute. */ - function onSubstituteNode(emitContext: EmitContext, node: Node) { + function onSubstituteNode(hint: EmitHint, node: Node) { if (node.id && noSubstitution && noSubstitution[node.id]) { - return previousOnSubstituteNode(emitContext, node); + return previousOnSubstituteNode(hint, node); } - node = previousOnSubstituteNode(emitContext, node); + node = previousOnSubstituteNode(hint, node); if (isPropertyAccessExpression(node)) { return substitutePropertyAccessExpression(node); } diff --git a/src/compiler/transformers/generators.ts b/src/compiler/transformers/generators.ts index 7dcfe76a427..ee17bdacbaf 100644 --- a/src/compiler/transformers/generators.ts +++ b/src/compiler/transformers/generators.ts @@ -1909,9 +1909,9 @@ namespace ts { return -1; } - function onSubstituteNode(emitContext: EmitContext, node: Node): Node { - node = previousOnSubstituteNode(emitContext, node); - if (emitContext === EmitContext.Expression) { + function onSubstituteNode(hint: EmitHint, node: Node): Node { + node = previousOnSubstituteNode(hint, node); + if (hint === EmitHint.Expression) { return substituteExpression(node); } return node; diff --git a/src/compiler/transformers/module/es2015.ts b/src/compiler/transformers/module/es2015.ts index 5611f890164..86fa1295f7b 100644 --- a/src/compiler/transformers/module/es2015.ts +++ b/src/compiler/transformers/module/es2015.ts @@ -71,18 +71,18 @@ namespace ts { /** * Hook for node emit. * - * @param emitContext A context hint for the emitter. + * @param hint A hint as to the intended usage of the node. * @param node The node to emit. * @param emit A callback used to emit the node in the printer. */ - function onEmitNode(emitContext: EmitContext, node: Node, emitCallback: (emitContext: EmitContext, node: Node) => void): void { + function onEmitNode(hint: EmitHint, node: Node, emitCallback: (hint: EmitHint, node: Node) => void): void { if (isSourceFile(node)) { currentSourceFile = node; - previousOnEmitNode(emitContext, node, emitCallback); + previousOnEmitNode(hint, node, emitCallback); currentSourceFile = undefined; } else { - previousOnEmitNode(emitContext, node, emitCallback); + previousOnEmitNode(hint, node, emitCallback); } } @@ -93,12 +93,12 @@ namespace ts { /** * Hooks node substitutions. * - * @param emitContext A context hint for the emitter. + * @param hint A hint as to the intended usage of the node. * @param node The node to substitute. */ - function onSubstituteNode(emitContext: EmitContext, node: Node) { - node = previousOnSubstituteNode(emitContext, node); - if (isIdentifier(node) && emitContext === EmitContext.Expression) { + function onSubstituteNode(hint: EmitHint, node: Node) { + node = previousOnSubstituteNode(hint, node); + if (isIdentifier(node) && hint === EmitHint.Expression) { return substituteExpressionIdentifier(node); } return node; diff --git a/src/compiler/transformers/module/module.ts b/src/compiler/transformers/module/module.ts index 0adea4fd540..e072429292a 100644 --- a/src/compiler/transformers/module/module.ts +++ b/src/compiler/transformers/module/module.ts @@ -1207,24 +1207,24 @@ namespace ts { /** * Hook for node emit notifications. * - * @param emitContext A context hint for the emitter. + * @param hint A hint as to the intended usage of the node. * @param node The node to emit. * @param emit A callback used to emit the node in the printer. */ - function onEmitNode(emitContext: EmitContext, node: Node, emitCallback: (emitContext: EmitContext, node: Node) => void): void { + function onEmitNode(hint: EmitHint, node: Node, emitCallback: (hint: EmitHint, node: Node) => void): void { if (node.kind === SyntaxKind.SourceFile) { currentSourceFile = node; currentModuleInfo = moduleInfoMap[getOriginalNodeId(currentSourceFile)]; noSubstitution = []; - previousOnEmitNode(emitContext, node, emitCallback); + previousOnEmitNode(hint, node, emitCallback); currentSourceFile = undefined; currentModuleInfo = undefined; noSubstitution = undefined; } else { - previousOnEmitNode(emitContext, node, emitCallback); + previousOnEmitNode(hint, node, emitCallback); } } @@ -1235,16 +1235,16 @@ namespace ts { /** * Hooks node substitutions. * - * @param emitContext A context hint for the emitter. + * @param hint A hint as to the intended usage of the node. * @param node The node to substitute. */ - function onSubstituteNode(emitContext: EmitContext, node: Node) { - node = previousOnSubstituteNode(emitContext, node); + function onSubstituteNode(hint: EmitHint, node: Node) { + node = previousOnSubstituteNode(hint, node); if (node.id && noSubstitution[node.id]) { return node; } - if (emitContext === EmitContext.Expression) { + if (hint === EmitHint.Expression) { return substituteExpression(node); } else if (isShorthandPropertyAssignment(node)) { diff --git a/src/compiler/transformers/module/system.ts b/src/compiler/transformers/module/system.ts index 3f1488b649d..6c59ea194cb 100644 --- a/src/compiler/transformers/module/system.ts +++ b/src/compiler/transformers/module/system.ts @@ -1548,11 +1548,11 @@ namespace ts { /** * Hook for node emit notifications. * - * @param emitContext A context hint for the emitter. + * @param hint A hint as to the intended usage of the node. * @param node The node to emit. - * @param emit A callback used to emit the node in the printer. + * @param emitCallback A callback used to emit the node in the printer. */ - function onEmitNode(emitContext: EmitContext, node: Node, emitCallback: (emitContext: EmitContext, node: Node) => void): void { + function onEmitNode(hint: EmitHint, node: Node, emitCallback: (hint: EmitHint, node: Node) => void): void { if (node.kind === SyntaxKind.SourceFile) { const id = getOriginalNodeId(node); currentSourceFile = node; @@ -1564,7 +1564,7 @@ namespace ts { delete noSubstitutionMap[id]; } - previousOnEmitNode(emitContext, node, emitCallback); + previousOnEmitNode(hint, node, emitCallback); currentSourceFile = undefined; moduleInfo = undefined; @@ -1572,7 +1572,7 @@ namespace ts { noSubstitution = undefined; } else { - previousOnEmitNode(emitContext, node, emitCallback); + previousOnEmitNode(hint, node, emitCallback); } } @@ -1583,16 +1583,16 @@ namespace ts { /** * Hooks node substitutions. * - * @param emitContext A context hint for the emitter. + * @param hint A hint as to the intended usage of the node. * @param node The node to substitute. */ - function onSubstituteNode(emitContext: EmitContext, node: Node) { - node = previousOnSubstituteNode(emitContext, node); + function onSubstituteNode(hint: EmitHint, node: Node) { + node = previousOnSubstituteNode(hint, node); if (isSubstitutionPrevented(node)) { return node; } - if (emitContext === EmitContext.Expression) { + if (hint === EmitHint.Expression) { return substituteExpression(node); } diff --git a/src/compiler/transformers/ts.ts b/src/compiler/transformers/ts.ts index e2b8b8fe2ec..a61998e8af9 100644 --- a/src/compiler/transformers/ts.ts +++ b/src/compiler/transformers/ts.ts @@ -3154,11 +3154,11 @@ namespace ts { /** * Hook for node emit. * - * @param emitContext A context hint for the emitter. + * @param hint A hint as to the intended usage of the node. * @param node The node to emit. * @param emit A callback used to emit the node in the printer. */ - function onEmitNode(emitContext: EmitContext, node: Node, emitCallback: (emitContext: EmitContext, node: Node) => void): void { + function onEmitNode(hint: EmitHint, node: Node, emitCallback: (hint: EmitHint, node: Node) => void): void { const savedApplicableSubstitutions = applicableSubstitutions; if (enabledSubstitutions & TypeScriptSubstitutionFlags.NamespaceExports && isTransformedModuleDeclaration(node)) { @@ -3169,7 +3169,7 @@ namespace ts { applicableSubstitutions |= TypeScriptSubstitutionFlags.NonQualifiedEnumMembers; } - previousOnEmitNode(emitContext, node, emitCallback); + previousOnEmitNode(hint, node, emitCallback); applicableSubstitutions = savedApplicableSubstitutions; } @@ -3177,12 +3177,12 @@ namespace ts { /** * Hooks node substitutions. * - * @param emitContext A context hint for the emitter. + * @param hint A hint as to the intended usage of the node. * @param node The node to substitute. */ - function onSubstituteNode(emitContext: EmitContext, node: Node) { - node = previousOnSubstituteNode(emitContext, node); - if (emitContext === EmitContext.Expression) { + function onSubstituteNode(hint: EmitHint, node: Node) { + node = previousOnSubstituteNode(hint, node); + if (hint === EmitHint.Expression) { return substituteExpression(node); } else if (isShorthandPropertyAssignment(node)) { diff --git a/src/compiler/tsconfig.json b/src/compiler/tsconfig.json index 52bb92ee1f0..54d5eb77e10 100644 --- a/src/compiler/tsconfig.json +++ b/src/compiler/tsconfig.json @@ -34,6 +34,7 @@ "comments.ts", "sourcemap.ts", "declarationEmitter.ts", + "printer.ts", "emitter.ts", "program.ts", "commandLineParser.ts", diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 8b49af402cf..682cd9e617b 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -348,6 +348,7 @@ EnumMember, // Top-level nodes SourceFile, + Bundle, // JSDoc nodes JSDocTypeExpression, @@ -557,15 +558,6 @@ export type ModifiersArray = NodeArray; - /*@internal*/ - export const enum GeneratedIdentifierKind { - None, // Not automatically generated. - Auto, // Automatically generated identifier. - Loop, // Automatically generated identifier with a preference for '_i'. - Unique, // Unique name based on the 'text' property. - Node, // Unique name based on the node in the 'original' property. - } - export interface Identifier extends PrimaryExpression { kind: SyntaxKind.Identifier; text: string; // Text of identifier (with escapes converted to characters) @@ -580,7 +572,14 @@ resolvedSymbol: Symbol; } - /*@internal*/ + export const enum GeneratedIdentifierKind { + None, // Not automatically generated. + Auto, // Automatically generated identifier. + Loop, // Automatically generated identifier with a preference for '_i'. + Unique, // Unique name based on the 'text' property. + Node, // Unique name based on the node in the 'original' property. + } + export interface GeneratedIdentifier extends Identifier { autoGenerateKind: GeneratedIdentifierKind.Auto | GeneratedIdentifierKind.Loop @@ -2201,6 +2200,11 @@ /* @internal */ ambientModuleNames: string[]; } + export interface Bundle extends Node { + kind: SyntaxKind.Bundle; + sourceFiles: SourceFile[]; + } + export interface ScriptReferenceHost { getCompilerOptions(): CompilerOptions; getSourceFile(fileName: string): SourceFile; @@ -3780,8 +3784,7 @@ LastEmitHelper = Generator } - /* @internal */ - export const enum EmitContext { + export const enum EmitHint { SourceFile, // Emitting a SourceFile Expression, // Emitting an Expression IdentifierName, // Emitting an IdentifierName @@ -3856,7 +3859,7 @@ * Hook used by transformers to substitute expressions just before they * are emitted by the pretty printer. */ - onSubstituteNode?: (emitContext: EmitContext, node: Node) => Node; + onSubstituteNode?: (hint: EmitHint, node: Node) => Node; /** * Enables before/after emit notifications in the pretty printer for the provided @@ -3874,7 +3877,7 @@ * Hook used to allow transformers to capture state before or after * the printer emits a node. */ - onEmitNode?: (emitContext: EmitContext, node: Node, emitCallback: (emitContext: EmitContext, node: Node) => void) => void; + onEmitNode?: (hint: EmitHint, node: Node, emitCallback: (hint: EmitHint, node: Node) => void) => void; } /* @internal */ @@ -3887,25 +3890,61 @@ /** * Emits the substitute for a node, if one is available; otherwise, emits the node. * - * @param emitContext The current emit context. + * @param hint A hint as to the intended usage of the node. * @param node The node to substitute. * @param emitCallback A callback used to emit the node or its substitute. */ - emitNodeWithSubstitution(emitContext: EmitContext, node: Node, emitCallback: (emitContext: EmitContext, node: Node) => void): void; + emitNodeWithSubstitution(hint: EmitHint, node: Node, emitCallback: (hint: EmitHint, node: Node) => void): void; /** * Emits a node with possible notification. * - * @param emitContext The current emit context. + * @param hint A hint as to the intended usage of the node. * @param node The node to emit. * @param emitCallback A callback used to emit the node. */ - emitNodeWithNotification(emitContext: EmitContext, node: Node, emitCallback: (emitContext: EmitContext, node: Node) => void): void; + emitNodeWithNotification(hint: EmitHint, node: Node, emitCallback: (hint: EmitHint, node: Node) => void): void; } /* @internal */ export type Transformer = (context: TransformationContext) => (node: SourceFile) => SourceFile; + export interface EmitTextWriter { + write(s: string): void; + writeTextOfNode(text: string, node: Node): void; + writeLine(): void; + increaseIndent(): void; + decreaseIndent(): void; + getText(): string; + rawWrite(s: string): void; + writeLiteral(s: string): void; + getTextPos(): number; + getLine(): number; + getColumn(): number; + getIndent(): number; + isAtStartOfLine(): boolean; + reset(): void; + } + + export interface Printer { + printNode(hint: EmitHint, node: Node, sourceFile: SourceFile): void; + printFile(sourceFile: SourceFile): void; + printBundle(bundle: Bundle): void; + } + + export interface PrinterOptions { + hasGlobalName?: (name: string) => boolean; + onEmitSourceMapOfNode?: (hint: EmitHint, node: Node, emitCallback: (hint: EmitHint, node: Node) => void) => void; + onEmitSourceMapOfToken?: (node: Node, token: SyntaxKind, pos: number, emitCallback: (token: SyntaxKind, pos: number) => number) => number; + onEmitCommentsOfNode?: (hint: EmitHint, node: Node, emitCallback: (hint: EmitHint, node: Node) => void) => void; + onEmitDetachedCommentsOfNode?: (node: Node, detachedRange: TextRange, emitCallback: (node: Node) => void) => void; + onEmitTrailingCommentsOfPosition?: (pos: number) => void; + onEmitNode?: (hint: EmitHint, node: Node, emitCallback: (hint: EmitHint, node: Node) => void) => void; + onEmitHelpers?: (node: Node, writeLines: (text: string) => void) => void; + onSetSourceFile?: (node: SourceFile) => void; + onSubstituteNode?: (hint: EmitHint, node: Node, emitCallback: (hint: EmitHint, node: Node) => void) => void; + } + export interface TextSpan { start: number; length: number; diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index 0a16875f8c0..5c92bfa65cc 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -2088,16 +2088,19 @@ namespace ts { return undefined; } - export function getOriginalSourceFiles(sourceFiles: SourceFile[]) { - const originalSourceFiles: SourceFile[] = []; - for (const sourceFile of sourceFiles) { - const originalSourceFile = getParseTreeNode(sourceFile, isSourceFile); - if (originalSourceFile) { - originalSourceFiles.push(originalSourceFile); - } + export function getOriginalSourceFileOrBundle(sourceFileOrBundle: SourceFile | Bundle) { + if (sourceFileOrBundle.kind === SyntaxKind.Bundle) { + return updateBundle(sourceFileOrBundle, sameMap(sourceFileOrBundle.sourceFiles, getOriginalSourceFile)); } + return getOriginalSourceFile(sourceFileOrBundle); + } - return originalSourceFiles; + function getOriginalSourceFile(sourceFile: SourceFile) { + return getParseTreeNode(sourceFile, isSourceFile) || sourceFile; + } + + export function getOriginalSourceFiles(sourceFiles: SourceFile[]) { + return sameMap(sourceFiles, getOriginalSourceFile); } export function getOriginalNodeId(node: Node) { @@ -2436,23 +2439,6 @@ namespace ts { s; } - export interface EmitTextWriter { - write(s: string): void; - writeTextOfNode(text: string, node: Node): void; - writeLine(): void; - increaseIndent(): void; - decreaseIndent(): void; - getText(): string; - rawWrite(s: string): void; - writeLiteral(s: string): void; - getTextPos(): number; - getLine(): number; - getColumn(): number; - getIndent(): number; - isAtStartOfLine(): boolean; - reset(): void; - } - const indentStrings: string[] = ["", " "]; export function getIndentString(level: number) { if (indentStrings[level] === undefined) { @@ -2635,7 +2621,7 @@ namespace ts { * Else, calls `getSourceFilesToEmit` with the (optional) target source file to determine the list of source files to emit. */ export function forEachEmittedFile( - host: EmitHost, action: (emitFileNames: EmitFileNames, sourceFiles: SourceFile[], isBundledEmit: boolean, emitOnlyDtsFiles: boolean) => void, + host: EmitHost, action: (emitFileNames: EmitFileNames, sourceFileOrBundle: SourceFile | Bundle, emitOnlyDtsFiles: boolean) => void, sourceFilesOrTargetSourceFile?: SourceFile[] | SourceFile, emitOnlyDtsFiles?: boolean) { @@ -2646,7 +2632,7 @@ namespace ts { const jsFilePath = options.outFile || options.out; const sourceMapFilePath = getSourceMapFilePath(jsFilePath, options); const declarationFilePath = options.declaration ? removeFileExtension(jsFilePath) + ".d.ts" : undefined; - action({ jsFilePath, sourceMapFilePath, declarationFilePath }, sourceFiles, /*isBundledEmit*/true, emitOnlyDtsFiles); + action({ jsFilePath, sourceMapFilePath, declarationFilePath }, createBundle(sourceFiles), emitOnlyDtsFiles); } } else { @@ -2654,7 +2640,7 @@ namespace ts { const jsFilePath = getOwnEmitOutputFilePath(sourceFile, host, getOutputExtension(sourceFile, options)); const sourceMapFilePath = getSourceMapFilePath(jsFilePath, options); const declarationFilePath = !isSourceFileJavaScript(sourceFile) && (emitOnlyDtsFiles || options.declaration) ? getDeclarationEmitOutputFilePath(sourceFile, host) : undefined; - action({ jsFilePath, sourceMapFilePath, declarationFilePath }, [sourceFile], /*isBundledEmit*/false, emitOnlyDtsFiles); + action({ jsFilePath, sourceMapFilePath, declarationFilePath }, sourceFile, emitOnlyDtsFiles); } } } diff --git a/src/harness/tsconfig.json b/src/harness/tsconfig.json index ebd07118cc5..d7bb935db89 100644 --- a/src/harness/tsconfig.json +++ b/src/harness/tsconfig.json @@ -37,6 +37,7 @@ "../compiler/comments.ts", "../compiler/sourcemap.ts", "../compiler/declarationEmitter.ts", + "../compiler/printer.ts", "../compiler/emitter.ts", "../compiler/program.ts", "../compiler/commandLineParser.ts", diff --git a/src/services/tsconfig.json b/src/services/tsconfig.json index b60e00292f5..493f3b45f93 100644 --- a/src/services/tsconfig.json +++ b/src/services/tsconfig.json @@ -34,6 +34,7 @@ "../compiler/comments.ts", "../compiler/sourcemap.ts", "../compiler/declarationEmitter.ts", + "../compiler/printer.ts", "../compiler/emitter.ts", "../compiler/program.ts", "../compiler/commandLineParser.ts", From cc8bd6fc09f160aff2d2e77e9c84c3afd95022ff Mon Sep 17 00:00:00 2001 From: gdh1995 Date: Sat, 28 Jan 2017 13:40:46 +0800 Subject: [PATCH 03/58] remove an odd new-line for catch clause --- src/compiler/emitter.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index 27285a4c2dc..8517d16d4e7 100644 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -1923,7 +1923,6 @@ namespace ts { } function emitCatchClause(node: CatchClause) { - writeLine(); const openParenPos = writeToken(SyntaxKind.CatchKeyword, node.pos); write(" "); writeToken(SyntaxKind.OpenParenToken, openParenPos); From 0165b71549533e3e6d810ffbe4dfb781b8794abc Mon Sep 17 00:00:00 2001 From: Ron Buckton Date: Mon, 30 Jan 2017 12:27:24 -0800 Subject: [PATCH 04/58] Embed comment emit inside of printer --- Jakefile.js | 2 - src/compiler/comments.ts | 30 +- src/compiler/core.ts | 4 +- src/compiler/emitter.ts | 2734 +++++++++++++++++++++++++++++++++++- src/compiler/printer.ts | 2659 ----------------------------------- src/compiler/tsconfig.json | 1 - src/compiler/types.ts | 72 +- src/compiler/utilities.ts | 19 +- src/harness/tsconfig.json | 1 - src/services/tsconfig.json | 1 - 10 files changed, 2793 insertions(+), 2730 deletions(-) delete mode 100644 src/compiler/printer.ts diff --git a/Jakefile.js b/Jakefile.js index a23b9cbe03c..3ee8476c842 100644 --- a/Jakefile.js +++ b/Jakefile.js @@ -84,7 +84,6 @@ var compilerSources = [ "sourcemap.ts", "comments.ts", "declarationEmitter.ts", - "printer.ts", "emitter.ts", "program.ts", "commandLineParser.ts", @@ -122,7 +121,6 @@ var servicesSources = [ "sourcemap.ts", "comments.ts", "declarationEmitter.ts", - "printer.ts", "emitter.ts", "program.ts", "commandLineParser.ts", diff --git a/src/compiler/comments.ts b/src/compiler/comments.ts index 3106d3ccfec..f69b4c546a0 100644 --- a/src/compiler/comments.ts +++ b/src/compiler/comments.ts @@ -5,13 +5,16 @@ namespace ts { export interface CommentWriter { reset(): void; setSourceFile(sourceFile: SourceFile): void; + setWriter(writer: EmitTextWriter): void; emitNodeWithComments(hint: EmitHint, node: Node, emitCallback: (hint: EmitHint, node: Node) => void): void; emitBodyWithDetachedComments(node: Node, detachedRange: TextRange, emitCallback: (node: Node) => void): void; emitTrailingCommentsOfPosition(pos: number): void; } - export function createCommentWriter(writer: EmitTextWriter, compilerOptions: CompilerOptions, newLine: string, emitPos: (pos: number) => void): CommentWriter { - const extendedDiagnostics = compilerOptions.extendedDiagnostics; + export function createCommentWriter(printerOptions: PrinterOptions, emitPos: (pos: number) => void): CommentWriter { + const extendedDiagnostics = printerOptions.extendedDiagnostics; + const newLine = getNewLineCharacter(printerOptions); + let writer: EmitTextWriter; let containerPos = -1; let containerEnd = -1; let declarationListContainerEnd = -1; @@ -20,10 +23,11 @@ namespace ts { let currentLineMap: number[]; let detachedCommentsInfo: { nodePos: number, detachedCommentEndPos: number}[]; let hasWrittenComment = false; - let disabled: boolean = compilerOptions.removeComments; + let disabled: boolean = printerOptions.removeComments; return { reset, + setWriter, setSourceFile, emitNodeWithComments, emitBodyWithDetachedComments, @@ -194,9 +198,9 @@ namespace ts { } // Leading comments are emitted at /*leading comment1 */space/*leading comment*/space - emitPos(commentPos); + if (emitPos) emitPos(commentPos); writeCommentRange(currentText, currentLineMap, writer, commentPos, commentEnd, newLine); - emitPos(commentEnd); + if (emitPos) emitPos(commentEnd); if (hasTrailingNewLine) { writer.writeLine(); @@ -216,9 +220,9 @@ namespace ts { writer.write(" "); } - emitPos(commentPos); + if (emitPos) emitPos(commentPos); writeCommentRange(currentText, currentLineMap, writer, commentPos, commentEnd, newLine); - emitPos(commentEnd); + if (emitPos) emitPos(commentEnd); if (hasTrailingNewLine) { writer.writeLine(); @@ -244,9 +248,9 @@ namespace ts { function emitTrailingCommentOfPosition(commentPos: number, commentEnd: number, _kind: SyntaxKind, hasTrailingNewLine: boolean) { // trailing comments of a position are emitted at /*trailing comment1 */space/*trailing comment*/space - emitPos(commentPos); + if (emitPos) emitPos(commentPos); writeCommentRange(currentText, currentLineMap, writer, commentPos, commentEnd, newLine); - emitPos(commentEnd); + if (emitPos) emitPos(commentEnd); if (hasTrailingNewLine) { writer.writeLine(); @@ -282,6 +286,10 @@ namespace ts { detachedCommentsInfo = undefined; } + function setWriter(output: EmitTextWriter): void { + writer = output; + } + function setSourceFile(sourceFile: SourceFile) { currentSourceFile = sourceFile; currentText = currentSourceFile.text; @@ -319,9 +327,9 @@ namespace ts { } function writeComment(text: string, lineMap: number[], writer: EmitTextWriter, commentPos: number, commentEnd: number, newLine: string) { - emitPos(commentPos); + if (emitPos) emitPos(commentPos); writeCommentRange(text, lineMap, writer, commentPos, commentEnd, newLine); - emitPos(commentEnd); + if (emitPos) emitPos(commentEnd); } /** diff --git a/src/compiler/core.ts b/src/compiler/core.ts index de3472afd88..b8097acaa71 100644 --- a/src/compiler/core.ts +++ b/src/compiler/core.ts @@ -1447,11 +1447,11 @@ namespace ts { return /^\.\.?($|[\\/])/.test(moduleName); } - export function getEmitScriptTarget(compilerOptions: CompilerOptions) { + export function getEmitScriptTarget(compilerOptions: CompilerOptions | PrinterOptions) { return compilerOptions.target || ScriptTarget.ES3; } - export function getEmitModuleKind(compilerOptions: CompilerOptions) { + export function getEmitModuleKind(compilerOptions: CompilerOptions | PrinterOptions) { return typeof compilerOptions.module === "number" ? compilerOptions.module : getEmitScriptTarget(compilerOptions) >= ScriptTarget.ES2015 ? ModuleKind.ES2015 : ModuleKind.CommonJS; diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index dd823cf7994..b3bd594ae88 100644 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -3,13 +3,12 @@ /// /// /// -/// -/* @internal */ namespace ts { - const id = (s: SourceFile) => s; - const nullTransformers: Transformer[] = [_ => id]; + const delimiters = createDelimiterMap(); + const brackets = createBracketsMap(); + /*@internal*/ // targetSourceFile is when users only want one file in entire project to be emitted. This is used in compileOnSave feature export function emitFiles(resolver: EmitResolver, host: EmitHost, targetSourceFile: SourceFile, emitOnlyDtsFiles?: boolean): EmitResult { const compilerOptions = host.getCompilerOptions(); @@ -17,10 +16,9 @@ namespace ts { const emittedFilesList: string[] = compilerOptions.listEmittedFiles ? [] : undefined; const emitterDiagnostics = createDiagnosticCollection(); const newLine = host.getNewLine(); - const transformers: Transformer[] = emitOnlyDtsFiles ? nullTransformers : getTransformers(compilerOptions); + const transformers = emitOnlyDtsFiles ? [] : getTransformers(compilerOptions); const writer = createTextWriter(newLine); const sourceMap = createSourceMapWriter(host, writer); - const comments = createCommentWriter(writer, compilerOptions, newLine, sourceMap.emitPos); let currentSourceFile: SourceFile; let bundledHelpers: Map; @@ -33,7 +31,7 @@ namespace ts { const transform = transformFiles(resolver, host, sourceFiles, transformers); // Create a printer to print the nodes - const printer = createPrinter(writer, compilerOptions, { + const printer = createPrinter(compilerOptions, { // resolver hooks hasGlobalName: resolver.hasGlobalName, @@ -44,11 +42,7 @@ namespace ts { // sourcemap hooks onEmitSourceMapOfNode: sourceMap.emitNodeWithSourceMap, onEmitSourceMapOfToken: sourceMap.emitTokenWithSourceMap, - - // comment hooks - onEmitCommentsOfNode: comments.emitNodeWithComments, - onEmitDetachedCommentsOfNode: comments.emitBodyWithDetachedComments, - onEmitTrailingCommentsOfPosition: comments.emitTrailingCommentsOfPosition, + onEmitSourceMapOfPosition: sourceMap.emitPos, // emitter hooks onEmitHelpers: emitHelpers, @@ -109,11 +103,11 @@ namespace ts { if (bundle) { bundledHelpers = createMap(); isOwnFileEmit = false; - printer.printBundle(bundle); + printer.writeBundle(bundle, writer); } else { isOwnFileEmit = true; - printer.printFile(sourceFile); + printer.writeFile(sourceFile, writer); } writer.writeLine(); @@ -138,7 +132,6 @@ namespace ts { // Reset state sourceMap.reset(); - comments.reset(); writer.reset(); currentSourceFile = undefined; @@ -149,7 +142,6 @@ namespace ts { function setSourceFile(node: SourceFile) { currentSourceFile = node; sourceMap.setSourceFile(node); - comments.setSourceFile(node); } function emitHelpers(node: Node, writeLines: (text: string) => void) { @@ -194,4 +186,2714 @@ namespace ts { return helpersEmitted; } } + + export function createPrinter(printerOptions: PrinterOptions = {}, handlers: PrintHandlers = {}): Printer { + const { + hasGlobalName, + onEmitSourceMapOfNode, + onEmitSourceMapOfToken, + onEmitSourceMapOfPosition, + onEmitNode, + onEmitHelpers, + onSetSourceFile, + onSubstituteNode, + } = handlers; + + const newLine = getNewLineCharacter(printerOptions); + const languageVersion = getEmitScriptTarget(printerOptions); + const moduleKind = getEmitModuleKind(printerOptions); + const comments = createCommentWriter(printerOptions, onEmitSourceMapOfPosition); + const { + emitNodeWithComments, + emitBodyWithDetachedComments, + emitTrailingCommentsOfPosition, + } = comments; + + let currentSourceFile: SourceFile; + let nodeIdToGeneratedName: string[]; // Map of generated names for specific nodes. + let autoGeneratedIdToGeneratedName: string[]; // Map of generated names for temp and loop variables. + let generatedNames: Map; // Set of names generated by the NameGenerator. + let tempFlagsStack: TempFlags[]; // Stack of enclosing name generation scopes. + let tempFlags: TempFlags; // TempFlags for the current name generation scope. + let writer: EmitTextWriter; + let ownWriter: EmitTextWriter; + + reset(); + return { + // public API + printNode, + printFile, + printBundle, + + // internal API + writeNode, + writeFile, + writeBundle + }; + + function printNode(hint: EmitHint, node: Node, sourceFile: SourceFile): string { + writeNode(hint, node, sourceFile, beginPrint()); + return endPrint(); + } + + function printBundle(bundle: Bundle): string { + writeBundle(bundle, beginPrint()); + return endPrint(); + } + + function printFile(sourceFile: SourceFile): string { + writeFile(sourceFile, beginPrint()); + return endPrint(); + } + + function writeNode(hint: EmitHint, node: Node, sourceFile: SourceFile, output: EmitTextWriter) { + const previousWriter = writer; + setWriter(output); + print(hint, node, sourceFile); + reset(); + writer = previousWriter; + } + + function writeBundle(bundle: Bundle, output: EmitTextWriter) { + const previousWriter = writer; + setWriter(output); + if (moduleKind) { + emitHelpersIndirect(bundle); + } + for (const sourceFile of bundle.sourceFiles) { + print(EmitHint.SourceFile, sourceFile, sourceFile); + } + reset(); + writer = previousWriter; + } + + function writeFile(sourceFile: SourceFile, output: EmitTextWriter) { + const previousWriter = writer; + setWriter(output); + print(EmitHint.SourceFile, sourceFile, sourceFile); + reset(); + writer = previousWriter; + } + + function beginPrint() { + return ownWriter || (ownWriter = createTextWriter(newLine)); + } + + function endPrint() { + const text = writer.getText(); + if (writer === ownWriter) { + writer.reset(); + } + + return text; + } + + function print(hint: EmitHint, node: Node, sourceFile: SourceFile) { + setSourceFile(sourceFile); + pipelineEmitWithNotification(hint, node); + } + + function setSourceFile(sourceFile: SourceFile) { + currentSourceFile = sourceFile; + comments.setSourceFile(sourceFile); + if (onSetSourceFile) { + onSetSourceFile(sourceFile); + } + } + + function setWriter(output: EmitTextWriter | undefined) { + writer = output; + comments.setWriter(output); + } + + function reset() { + nodeIdToGeneratedName = []; + autoGeneratedIdToGeneratedName = []; + generatedNames = createMap(); + tempFlagsStack = []; + tempFlags = TempFlags.Auto; + comments.reset(); + setWriter(/*output*/ undefined); + } + + function emit(node: Node, hint = EmitHint.Unspecified) { + pipelineEmitWithNotification(hint, node); + } + + function emitIdentifierName(node: Identifier) { + pipelineEmitWithNotification(EmitHint.IdentifierName, node); + } + + function emitExpression(node: Expression) { + pipelineEmitWithNotification(EmitHint.Expression, node); + } + + function pipelineEmitWithNotification(hint: EmitHint, node: Node) { + if (onEmitNode) { + onEmitNode(hint, node, pipelineEmitWithComments); + } + else { + pipelineEmitWithComments(hint, node); + } + } + + function pipelineEmitWithComments(hint: EmitHint, node: Node) { + if (emitNodeWithComments && hint !== EmitHint.SourceFile) { + emitNodeWithComments(hint, node, pipelineEmitWithSourceMap); + } + else { + pipelineEmitWithSourceMap(hint, node); + } + } + + function pipelineEmitWithSourceMap(hint: EmitHint, node: Node) { + if (onEmitSourceMapOfNode && hint !== EmitHint.SourceFile && hint !== EmitHint.IdentifierName) { + onEmitSourceMapOfNode(hint, node, pipelineEmitWithSubstitution); + } + else { + pipelineEmitWithSubstitution(hint, node); + } + } + + function pipelineEmitWithSubstitution(hint: EmitHint, node: Node) { + if (onSubstituteNode) { + onSubstituteNode(hint, node, pipelineEmitWithHint); + } + else { + pipelineEmitWithHint(hint, node); + } + } + + function pipelineEmitWithHint(hint: EmitHint, node: Node): void { + switch (hint) { + case EmitHint.SourceFile: return pipelineEmitSourceFile(node); + case EmitHint.IdentifierName: return pipelineEmitIdentifierName(node); + case EmitHint.Expression: return pipelineEmitExpression(node); + case EmitHint.Unspecified: return pipelineEmitUnspecified(node); + } + } + + function pipelineEmitSourceFile(node: Node): void { + Debug.assertNode(node, isSourceFile); + emitSourceFile(node); + } + + function pipelineEmitIdentifierName(node: Node): void { + Debug.assertNode(node, isIdentifier); + emitIdentifier(node); + } + + function pipelineEmitUnspecified(node: Node): void { + const kind = node.kind; + switch (kind) { + // Pseudo-literals + case SyntaxKind.TemplateHead: + case SyntaxKind.TemplateMiddle: + case SyntaxKind.TemplateTail: + return emitLiteral(node); + + // Identifiers + case SyntaxKind.Identifier: + return emitIdentifier(node); + + // Reserved words + case SyntaxKind.ConstKeyword: + case SyntaxKind.DefaultKeyword: + case SyntaxKind.ExportKeyword: + case SyntaxKind.VoidKeyword: + + // Strict mode reserved words + case SyntaxKind.PrivateKeyword: + case SyntaxKind.ProtectedKeyword: + case SyntaxKind.PublicKeyword: + case SyntaxKind.StaticKeyword: + + // Contextual keywords + case SyntaxKind.AbstractKeyword: + case SyntaxKind.AsKeyword: + case SyntaxKind.AnyKeyword: + case SyntaxKind.AsyncKeyword: + case SyntaxKind.AwaitKeyword: + case SyntaxKind.BooleanKeyword: + case SyntaxKind.ConstructorKeyword: + case SyntaxKind.DeclareKeyword: + case SyntaxKind.GetKeyword: + case SyntaxKind.IsKeyword: + case SyntaxKind.ModuleKeyword: + case SyntaxKind.NamespaceKeyword: + case SyntaxKind.NeverKeyword: + case SyntaxKind.ReadonlyKeyword: + case SyntaxKind.RequireKeyword: + case SyntaxKind.NumberKeyword: + case SyntaxKind.SetKeyword: + case SyntaxKind.StringKeyword: + case SyntaxKind.SymbolKeyword: + case SyntaxKind.TypeKeyword: + case SyntaxKind.UndefinedKeyword: + case SyntaxKind.FromKeyword: + case SyntaxKind.GlobalKeyword: + case SyntaxKind.OfKeyword: + writeTokenText(kind); + return; + + // Parse tree nodes + + // Names + case SyntaxKind.QualifiedName: + return emitQualifiedName(node); + case SyntaxKind.ComputedPropertyName: + return emitComputedPropertyName(node); + + // Signature elements + case SyntaxKind.TypeParameter: + return emitTypeParameter(node); + case SyntaxKind.Parameter: + return emitParameter(node); + case SyntaxKind.Decorator: + return emitDecorator(node); + + // Type members + case SyntaxKind.PropertySignature: + return emitPropertySignature(node); + case SyntaxKind.PropertyDeclaration: + return emitPropertyDeclaration(node); + case SyntaxKind.MethodSignature: + return emitMethodSignature(node); + case SyntaxKind.MethodDeclaration: + return emitMethodDeclaration(node); + case SyntaxKind.Constructor: + return emitConstructor(node); + case SyntaxKind.GetAccessor: + case SyntaxKind.SetAccessor: + return emitAccessorDeclaration(node); + case SyntaxKind.CallSignature: + return emitCallSignature(node); + case SyntaxKind.ConstructSignature: + return emitConstructSignature(node); + case SyntaxKind.IndexSignature: + return emitIndexSignature(node); + + // Types + case SyntaxKind.TypePredicate: + return emitTypePredicate(node); + case SyntaxKind.TypeReference: + return emitTypeReference(node); + case SyntaxKind.FunctionType: + return emitFunctionType(node); + case SyntaxKind.ConstructorType: + return emitConstructorType(node); + case SyntaxKind.TypeQuery: + return emitTypeQuery(node); + case SyntaxKind.TypeLiteral: + return emitTypeLiteral(node); + case SyntaxKind.ArrayType: + return emitArrayType(node); + case SyntaxKind.TupleType: + return emitTupleType(node); + case SyntaxKind.UnionType: + return emitUnionType(node); + case SyntaxKind.IntersectionType: + return emitIntersectionType(node); + case SyntaxKind.ParenthesizedType: + return emitParenthesizedType(node); + case SyntaxKind.ExpressionWithTypeArguments: + return emitExpressionWithTypeArguments(node); + case SyntaxKind.ThisType: + return emitThisType(); + case SyntaxKind.TypeOperator: + return emitTypeOperator(node); + case SyntaxKind.IndexedAccessType: + return emitIndexedAccessType(node); + case SyntaxKind.MappedType: + return emitMappedType(node); + case SyntaxKind.LiteralType: + return emitLiteralType(node); + + // Binding patterns + case SyntaxKind.ObjectBindingPattern: + return emitObjectBindingPattern(node); + case SyntaxKind.ArrayBindingPattern: + return emitArrayBindingPattern(node); + case SyntaxKind.BindingElement: + return emitBindingElement(node); + + // Misc + case SyntaxKind.TemplateSpan: + return emitTemplateSpan(node); + case SyntaxKind.SemicolonClassElement: + return emitSemicolonClassElement(); + + // Statements + case SyntaxKind.Block: + return emitBlock(node); + case SyntaxKind.VariableStatement: + return emitVariableStatement(node); + case SyntaxKind.EmptyStatement: + return emitEmptyStatement(); + case SyntaxKind.ExpressionStatement: + return emitExpressionStatement(node); + case SyntaxKind.IfStatement: + return emitIfStatement(node); + case SyntaxKind.DoStatement: + return emitDoStatement(node); + case SyntaxKind.WhileStatement: + return emitWhileStatement(node); + case SyntaxKind.ForStatement: + return emitForStatement(node); + case SyntaxKind.ForInStatement: + return emitForInStatement(node); + case SyntaxKind.ForOfStatement: + return emitForOfStatement(node); + case SyntaxKind.ContinueStatement: + return emitContinueStatement(node); + case SyntaxKind.BreakStatement: + return emitBreakStatement(node); + case SyntaxKind.ReturnStatement: + return emitReturnStatement(node); + case SyntaxKind.WithStatement: + return emitWithStatement(node); + case SyntaxKind.SwitchStatement: + return emitSwitchStatement(node); + case SyntaxKind.LabeledStatement: + return emitLabeledStatement(node); + case SyntaxKind.ThrowStatement: + return emitThrowStatement(node); + case SyntaxKind.TryStatement: + return emitTryStatement(node); + case SyntaxKind.DebuggerStatement: + return emitDebuggerStatement(node); + + // Declarations + case SyntaxKind.VariableDeclaration: + return emitVariableDeclaration(node); + case SyntaxKind.VariableDeclarationList: + return emitVariableDeclarationList(node); + case SyntaxKind.FunctionDeclaration: + return emitFunctionDeclaration(node); + case SyntaxKind.ClassDeclaration: + return emitClassDeclaration(node); + case SyntaxKind.InterfaceDeclaration: + return emitInterfaceDeclaration(node); + case SyntaxKind.TypeAliasDeclaration: + return emitTypeAliasDeclaration(node); + case SyntaxKind.EnumDeclaration: + return emitEnumDeclaration(node); + case SyntaxKind.ModuleDeclaration: + return emitModuleDeclaration(node); + case SyntaxKind.ModuleBlock: + return emitModuleBlock(node); + case SyntaxKind.CaseBlock: + return emitCaseBlock(node); + case SyntaxKind.ImportEqualsDeclaration: + return emitImportEqualsDeclaration(node); + case SyntaxKind.ImportDeclaration: + return emitImportDeclaration(node); + case SyntaxKind.ImportClause: + return emitImportClause(node); + case SyntaxKind.NamespaceImport: + return emitNamespaceImport(node); + case SyntaxKind.NamedImports: + return emitNamedImports(node); + case SyntaxKind.ImportSpecifier: + return emitImportSpecifier(node); + case SyntaxKind.ExportAssignment: + return emitExportAssignment(node); + case SyntaxKind.ExportDeclaration: + return emitExportDeclaration(node); + case SyntaxKind.NamedExports: + return emitNamedExports(node); + case SyntaxKind.ExportSpecifier: + return emitExportSpecifier(node); + case SyntaxKind.MissingDeclaration: + return; + + // Module references + case SyntaxKind.ExternalModuleReference: + return emitExternalModuleReference(node); + + // JSX (non-expression) + case SyntaxKind.JsxText: + return emitJsxText(node); + case SyntaxKind.JsxOpeningElement: + return emitJsxOpeningElement(node); + case SyntaxKind.JsxClosingElement: + return emitJsxClosingElement(node); + case SyntaxKind.JsxAttribute: + return emitJsxAttribute(node); + case SyntaxKind.JsxSpreadAttribute: + return emitJsxSpreadAttribute(node); + case SyntaxKind.JsxExpression: + return emitJsxExpression(node); + + // Clauses + case SyntaxKind.CaseClause: + return emitCaseClause(node); + case SyntaxKind.DefaultClause: + return emitDefaultClause(node); + case SyntaxKind.HeritageClause: + return emitHeritageClause(node); + case SyntaxKind.CatchClause: + return emitCatchClause(node); + + // Property assignments + case SyntaxKind.PropertyAssignment: + return emitPropertyAssignment(node); + case SyntaxKind.ShorthandPropertyAssignment: + return emitShorthandPropertyAssignment(node); + case SyntaxKind.SpreadAssignment: + return emitSpreadAssignment(node as SpreadAssignment); + + // Enum + case SyntaxKind.EnumMember: + return emitEnumMember(node); + + // JSDoc nodes (ignored) + // Transformation nodes (ignored) + } + + // If the node is an expression, try to emit it as an expression with + // substitution. + if (isExpression(node)) { + return pipelineEmitWithSubstitution(EmitHint.Expression, node); + } + } + + function pipelineEmitExpression(node: Node): void { + const kind = node.kind; + switch (kind) { + // Literals + case SyntaxKind.NumericLiteral: + return emitNumericLiteral(node); + + case SyntaxKind.StringLiteral: + case SyntaxKind.RegularExpressionLiteral: + case SyntaxKind.NoSubstitutionTemplateLiteral: + return emitLiteral(node); + + // Identifiers + case SyntaxKind.Identifier: + return emitIdentifier(node); + + // Reserved words + case SyntaxKind.FalseKeyword: + case SyntaxKind.NullKeyword: + case SyntaxKind.SuperKeyword: + case SyntaxKind.TrueKeyword: + case SyntaxKind.ThisKeyword: + writeTokenText(kind); + return; + + // Expressions + case SyntaxKind.ArrayLiteralExpression: + return emitArrayLiteralExpression(node); + case SyntaxKind.ObjectLiteralExpression: + return emitObjectLiteralExpression(node); + case SyntaxKind.PropertyAccessExpression: + return emitPropertyAccessExpression(node); + case SyntaxKind.ElementAccessExpression: + return emitElementAccessExpression(node); + case SyntaxKind.CallExpression: + return emitCallExpression(node); + case SyntaxKind.NewExpression: + return emitNewExpression(node); + case SyntaxKind.TaggedTemplateExpression: + return emitTaggedTemplateExpression(node); + case SyntaxKind.TypeAssertionExpression: + return emitTypeAssertionExpression(node); + case SyntaxKind.ParenthesizedExpression: + return emitParenthesizedExpression(node); + case SyntaxKind.FunctionExpression: + return emitFunctionExpression(node); + case SyntaxKind.ArrowFunction: + return emitArrowFunction(node); + case SyntaxKind.DeleteExpression: + return emitDeleteExpression(node); + case SyntaxKind.TypeOfExpression: + return emitTypeOfExpression(node); + case SyntaxKind.VoidExpression: + return emitVoidExpression(node); + case SyntaxKind.AwaitExpression: + return emitAwaitExpression(node); + case SyntaxKind.PrefixUnaryExpression: + return emitPrefixUnaryExpression(node); + case SyntaxKind.PostfixUnaryExpression: + return emitPostfixUnaryExpression(node); + case SyntaxKind.BinaryExpression: + return emitBinaryExpression(node); + case SyntaxKind.ConditionalExpression: + return emitConditionalExpression(node); + case SyntaxKind.TemplateExpression: + return emitTemplateExpression(node); + case SyntaxKind.YieldExpression: + return emitYieldExpression(node); + case SyntaxKind.SpreadElement: + return emitSpreadExpression(node); + case SyntaxKind.ClassExpression: + return emitClassExpression(node); + case SyntaxKind.OmittedExpression: + return; + case SyntaxKind.AsExpression: + return emitAsExpression(node); + case SyntaxKind.NonNullExpression: + return emitNonNullExpression(node); + case SyntaxKind.MetaProperty: + return emitMetaProperty(node); + + // JSX + case SyntaxKind.JsxElement: + return emitJsxElement(node); + case SyntaxKind.JsxSelfClosingElement: + return emitJsxSelfClosingElement(node); + + // Transformation nodes + case SyntaxKind.PartiallyEmittedExpression: + return emitPartiallyEmittedExpression(node); + } + } + + function emitBodyIndirect(node: Node, elements: NodeArray, emitCallback: (node: Node) => void): void { + if (emitBodyWithDetachedComments) { + emitBodyWithDetachedComments(node, elements, emitCallback); + } + else { + emitCallback(node); + } + } + + function emitHelpersIndirect(node: Node) { + if (onEmitHelpers) { + onEmitHelpers(node, writeLines); + } + } + + // + // Literals/Pseudo-literals + // + + // SyntaxKind.NumericLiteral + function emitNumericLiteral(node: NumericLiteral) { + emitLiteral(node); + if (node.trailingComment) { + write(` /*${node.trailingComment}*/`); + } + } + + // SyntaxKind.StringLiteral + // SyntaxKind.RegularExpressionLiteral + // SyntaxKind.NoSubstitutionTemplateLiteral + // SyntaxKind.TemplateHead + // SyntaxKind.TemplateMiddle + // SyntaxKind.TemplateTail + function emitLiteral(node: LiteralLikeNode) { + const text = getLiteralTextOfNode(node); + if ((printerOptions.sourceMap || printerOptions.inlineSourceMap) + && (node.kind === SyntaxKind.StringLiteral || isTemplateLiteralKind(node.kind))) { + writer.writeLiteral(text); + } + else { + write(text); + } + } + + // + // Identifiers + // + + function emitIdentifier(node: Identifier) { + write(getTextOfNode(node, /*includeTrivia*/ false)); + } + + // + // Names + // + + function emitQualifiedName(node: QualifiedName) { + emitEntityName(node.left); + write("."); + emit(node.right); + } + + function emitEntityName(node: EntityName) { + if (node.kind === SyntaxKind.Identifier) { + emitExpression(node); + } + else { + emit(node); + } + } + + function emitComputedPropertyName(node: ComputedPropertyName) { + write("["); + emitExpression(node.expression); + write("]"); + } + + // + // Signature elements + // + + function emitTypeParameter(node: TypeParameterDeclaration) { + emit(node.name); + emitWithPrefix(" extends ", node.constraint); + } + + function emitParameter(node: ParameterDeclaration) { + emitDecorators(node, node.decorators); + emitModifiers(node, node.modifiers); + writeIfPresent(node.dotDotDotToken, "..."); + emit(node.name); + writeIfPresent(node.questionToken, "?"); + emitExpressionWithPrefix(" = ", node.initializer); + emitWithPrefix(": ", node.type); + } + + function emitDecorator(decorator: Decorator) { + write("@"); + emitExpression(decorator.expression); + } + + // + // Type members + // + + function emitPropertySignature(node: PropertySignature) { + emitDecorators(node, node.decorators); + emitModifiers(node, node.modifiers); + emit(node.name); + writeIfPresent(node.questionToken, "?"); + emitWithPrefix(": ", node.type); + write(";"); + } + + function emitPropertyDeclaration(node: PropertyDeclaration) { + emitDecorators(node, node.decorators); + emitModifiers(node, node.modifiers); + emit(node.name); + emitWithPrefix(": ", node.type); + emitExpressionWithPrefix(" = ", node.initializer); + write(";"); + } + + function emitMethodSignature(node: MethodSignature) { + emitDecorators(node, node.decorators); + emitModifiers(node, node.modifiers); + emit(node.name); + writeIfPresent(node.questionToken, "?"); + emitTypeParameters(node, node.typeParameters); + emitParameters(node, node.parameters); + emitWithPrefix(": ", node.type); + write(";"); + } + + function emitMethodDeclaration(node: MethodDeclaration) { + emitDecorators(node, node.decorators); + emitModifiers(node, node.modifiers); + writeIfPresent(node.asteriskToken, "*"); + emit(node.name); + emitSignatureAndBody(node, emitSignatureHead); + } + + function emitConstructor(node: ConstructorDeclaration) { + emitModifiers(node, node.modifiers); + write("constructor"); + emitSignatureAndBody(node, emitSignatureHead); + } + + function emitAccessorDeclaration(node: AccessorDeclaration) { + emitDecorators(node, node.decorators); + emitModifiers(node, node.modifiers); + write(node.kind === SyntaxKind.GetAccessor ? "get " : "set "); + emit(node.name); + emitSignatureAndBody(node, emitSignatureHead); + } + + function emitCallSignature(node: CallSignatureDeclaration) { + emitDecorators(node, node.decorators); + emitModifiers(node, node.modifiers); + emitTypeParameters(node, node.typeParameters); + emitParameters(node, node.parameters); + emitWithPrefix(": ", node.type); + write(";"); + } + + function emitConstructSignature(node: ConstructSignatureDeclaration) { + emitDecorators(node, node.decorators); + emitModifiers(node, node.modifiers); + write("new "); + emitTypeParameters(node, node.typeParameters); + emitParameters(node, node.parameters); + emitWithPrefix(": ", node.type); + write(";"); + } + + function emitIndexSignature(node: IndexSignatureDeclaration) { + emitDecorators(node, node.decorators); + emitModifiers(node, node.modifiers); + emitParametersForIndexSignature(node, node.parameters); + emitWithPrefix(": ", node.type); + write(";"); + } + + function emitSemicolonClassElement() { + write(";"); + } + + // + // Types + // + + function emitTypePredicate(node: TypePredicateNode) { + emit(node.parameterName); + write(" is "); + emit(node.type); + } + + function emitTypeReference(node: TypeReferenceNode) { + emit(node.typeName); + emitTypeArguments(node, node.typeArguments); + } + + function emitFunctionType(node: FunctionTypeNode) { + emitTypeParameters(node, node.typeParameters); + emitParametersForArrow(node, node.parameters); + write(" => "); + emit(node.type); + } + + function emitConstructorType(node: ConstructorTypeNode) { + write("new "); + emitTypeParameters(node, node.typeParameters); + emitParametersForArrow(node, node.parameters); + write(" => "); + emit(node.type); + } + + function emitTypeQuery(node: TypeQueryNode) { + write("typeof "); + emit(node.exprName); + } + + function emitTypeLiteral(node: TypeLiteralNode) { + write("{"); + emitList(node, node.members, ListFormat.TypeLiteralMembers); + write("}"); + } + + function emitArrayType(node: ArrayTypeNode) { + emit(node.elementType); + write("[]"); + } + + function emitTupleType(node: TupleTypeNode) { + write("["); + emitList(node, node.elementTypes, ListFormat.TupleTypeElements); + write("]"); + } + + function emitUnionType(node: UnionTypeNode) { + emitList(node, node.types, ListFormat.UnionTypeConstituents); + } + + function emitIntersectionType(node: IntersectionTypeNode) { + emitList(node, node.types, ListFormat.IntersectionTypeConstituents); + } + + function emitParenthesizedType(node: ParenthesizedTypeNode) { + write("("); + emit(node.type); + write(")"); + } + + function emitThisType() { + write("this"); + } + + function emitTypeOperator(node: TypeOperatorNode) { + writeTokenText(node.operator); + write(" "); + emit(node.type); + } + + function emitIndexedAccessType(node: IndexedAccessTypeNode) { + emit(node.objectType); + write("["); + emit(node.indexType); + write("]"); + } + + function emitMappedType(node: MappedTypeNode) { + write("{"); + writeLine(); + increaseIndent(); + writeIfPresent(node.readonlyToken, "readonly "); + write("["); + emit(node.typeParameter.name); + write(" in "); + emit(node.typeParameter.constraint); + write("]"); + writeIfPresent(node.questionToken, "?"); + write(": "); + emit(node.type); + write(";"); + writeLine(); + decreaseIndent(); + write("}"); + } + + function emitLiteralType(node: LiteralTypeNode) { + emitExpression(node.literal); + } + + // + // Binding patterns + // + + function emitObjectBindingPattern(node: ObjectBindingPattern) { + const elements = node.elements; + if (elements.length === 0) { + write("{}"); + } + else { + write("{"); + emitList(node, elements, ListFormat.ObjectBindingPatternElements); + write("}"); + } + } + + function emitArrayBindingPattern(node: ArrayBindingPattern) { + const elements = node.elements; + if (elements.length === 0) { + write("[]"); + } + else { + write("["); + emitList(node, node.elements, ListFormat.ArrayBindingPatternElements); + write("]"); + } + } + + function emitBindingElement(node: BindingElement) { + emitWithSuffix(node.propertyName, ": "); + writeIfPresent(node.dotDotDotToken, "..."); + emit(node.name); + emitExpressionWithPrefix(" = ", node.initializer); + } + + // + // Expressions + // + + function emitArrayLiteralExpression(node: ArrayLiteralExpression) { + const elements = node.elements; + if (elements.length === 0) { + write("[]"); + } + else { + const preferNewLine = node.multiLine ? ListFormat.PreferNewLine : ListFormat.None; + emitExpressionList(node, elements, ListFormat.ArrayLiteralExpressionElements | preferNewLine); + } + } + + function emitObjectLiteralExpression(node: ObjectLiteralExpression) { + const properties = node.properties; + if (properties.length === 0) { + write("{}"); + } + else { + const indentedFlag = getEmitFlags(node) & EmitFlags.Indented; + if (indentedFlag) { + increaseIndent(); + } + + const preferNewLine = node.multiLine ? ListFormat.PreferNewLine : ListFormat.None; + const allowTrailingComma = languageVersion >= ScriptTarget.ES5 ? ListFormat.AllowTrailingComma : ListFormat.None; + emitList(node, properties, ListFormat.ObjectLiteralExpressionProperties | allowTrailingComma | preferNewLine); + + if (indentedFlag) { + decreaseIndent(); + } + } + } + + function emitPropertyAccessExpression(node: PropertyAccessExpression) { + let indentBeforeDot = false; + let indentAfterDot = false; + if (!(getEmitFlags(node) & EmitFlags.NoIndentation)) { + const dotRangeStart = node.expression.end; + const dotRangeEnd = skipTrivia(currentSourceFile.text, node.expression.end) + 1; + const dotToken = { kind: SyntaxKind.DotToken, pos: dotRangeStart, end: dotRangeEnd }; + indentBeforeDot = needsIndentation(node, node.expression, dotToken); + indentAfterDot = needsIndentation(node, dotToken, node.name); + } + + emitExpression(node.expression); + increaseIndentIf(indentBeforeDot); + + const shouldEmitDotDot = !indentBeforeDot && needsDotDotForPropertyAccess(node.expression); + write(shouldEmitDotDot ? ".." : "."); + + increaseIndentIf(indentAfterDot); + emit(node.name); + decreaseIndentIf(indentBeforeDot, indentAfterDot); + } + + // 1..toString is a valid property access, emit a dot after the literal + // Also emit a dot if expression is a integer const enum value - it will appear in generated code as numeric literal + function needsDotDotForPropertyAccess(expression: Expression) { + if (expression.kind === SyntaxKind.NumericLiteral) { + // check if numeric literal is a decimal literal that was originally written with a dot + const text = getLiteralTextOfNode(expression); + return getNumericLiteralFlags(text, /*hint*/ NumericLiteralFlags.All) === NumericLiteralFlags.None + && !(expression).isOctalLiteral + && text.indexOf(tokenToString(SyntaxKind.DotToken)) < 0; + } + else if (isPropertyAccessExpression(expression) || isElementAccessExpression(expression)) { + // check if constant enum value is integer + const constantValue = getConstantValue(expression); + // isFinite handles cases when constantValue is undefined + return isFinite(constantValue) + && Math.floor(constantValue) === constantValue + && printerOptions.removeComments; + } + } + + function emitElementAccessExpression(node: ElementAccessExpression) { + emitExpression(node.expression); + write("["); + emitExpression(node.argumentExpression); + write("]"); + } + + function emitCallExpression(node: CallExpression) { + emitExpression(node.expression); + emitTypeArguments(node, node.typeArguments); + emitExpressionList(node, node.arguments, ListFormat.CallExpressionArguments); + } + + function emitNewExpression(node: NewExpression) { + write("new "); + emitExpression(node.expression); + emitTypeArguments(node, node.typeArguments); + emitExpressionList(node, node.arguments, ListFormat.NewExpressionArguments); + } + + function emitTaggedTemplateExpression(node: TaggedTemplateExpression) { + emitExpression(node.tag); + write(" "); + emitExpression(node.template); + } + + function emitTypeAssertionExpression(node: TypeAssertion) { + write("<"); + emit(node.type); + write(">"); + emitExpression(node.expression); + } + + function emitParenthesizedExpression(node: ParenthesizedExpression) { + write("("); + emitExpression(node.expression); + write(")"); + } + + function emitFunctionExpression(node: FunctionExpression) { + emitFunctionDeclarationOrExpression(node); + } + + function emitArrowFunction(node: ArrowFunction) { + emitDecorators(node, node.decorators); + emitModifiers(node, node.modifiers); + emitSignatureAndBody(node, emitArrowFunctionHead); + } + + function emitArrowFunctionHead(node: ArrowFunction) { + emitTypeParameters(node, node.typeParameters); + emitParametersForArrow(node, node.parameters); + emitWithPrefix(": ", node.type); + write(" =>"); + } + + function emitDeleteExpression(node: DeleteExpression) { + write("delete "); + emitExpression(node.expression); + } + + function emitTypeOfExpression(node: TypeOfExpression) { + write("typeof "); + emitExpression(node.expression); + } + + function emitVoidExpression(node: VoidExpression) { + write("void "); + emitExpression(node.expression); + } + + function emitAwaitExpression(node: AwaitExpression) { + write("await "); + emitExpression(node.expression); + } + + function emitPrefixUnaryExpression(node: PrefixUnaryExpression) { + writeTokenText(node.operator); + if (shouldEmitWhitespaceBeforeOperand(node)) { + write(" "); + } + emitExpression(node.operand); + } + + function shouldEmitWhitespaceBeforeOperand(node: PrefixUnaryExpression) { + // In some cases, we need to emit a space between the operator and the operand. One obvious case + // is when the operator is an identifier, like delete or typeof. We also need to do this for plus + // and minus expressions in certain cases. Specifically, consider the following two cases (parens + // are just for clarity of exposition, and not part of the source code): + // + // (+(+1)) + // (+(++1)) + // + // We need to emit a space in both cases. In the first case, the absence of a space will make + // the resulting expression a prefix increment operation. And in the second, it will make the resulting + // expression a prefix increment whose operand is a plus expression - (++(+x)) + // The same is true of minus of course. + const operand = node.operand; + return operand.kind === SyntaxKind.PrefixUnaryExpression + && ((node.operator === SyntaxKind.PlusToken && ((operand).operator === SyntaxKind.PlusToken || (operand).operator === SyntaxKind.PlusPlusToken)) + || (node.operator === SyntaxKind.MinusToken && ((operand).operator === SyntaxKind.MinusToken || (operand).operator === SyntaxKind.MinusMinusToken))); + } + + function emitPostfixUnaryExpression(node: PostfixUnaryExpression) { + emitExpression(node.operand); + writeTokenText(node.operator); + } + + function emitBinaryExpression(node: BinaryExpression) { + const isCommaOperator = node.operatorToken.kind !== SyntaxKind.CommaToken; + const indentBeforeOperator = needsIndentation(node, node.left, node.operatorToken); + const indentAfterOperator = needsIndentation(node, node.operatorToken, node.right); + + emitExpression(node.left); + increaseIndentIf(indentBeforeOperator, isCommaOperator ? " " : undefined); + writeTokenText(node.operatorToken.kind); + increaseIndentIf(indentAfterOperator, " "); + emitExpression(node.right); + decreaseIndentIf(indentBeforeOperator, indentAfterOperator); + } + + function emitConditionalExpression(node: ConditionalExpression) { + const indentBeforeQuestion = needsIndentation(node, node.condition, node.questionToken); + const indentAfterQuestion = needsIndentation(node, node.questionToken, node.whenTrue); + const indentBeforeColon = needsIndentation(node, node.whenTrue, node.colonToken); + const indentAfterColon = needsIndentation(node, node.colonToken, node.whenFalse); + + emitExpression(node.condition); + increaseIndentIf(indentBeforeQuestion, " "); + write("?"); + increaseIndentIf(indentAfterQuestion, " "); + emitExpression(node.whenTrue); + decreaseIndentIf(indentBeforeQuestion, indentAfterQuestion); + + increaseIndentIf(indentBeforeColon, " "); + write(":"); + increaseIndentIf(indentAfterColon, " "); + emitExpression(node.whenFalse); + decreaseIndentIf(indentBeforeColon, indentAfterColon); + } + + function emitTemplateExpression(node: TemplateExpression) { + emit(node.head); + emitList(node, node.templateSpans, ListFormat.TemplateExpressionSpans); + } + + function emitYieldExpression(node: YieldExpression) { + write(node.asteriskToken ? "yield*" : "yield"); + emitExpressionWithPrefix(" ", node.expression); + } + + function emitSpreadExpression(node: SpreadElement) { + write("..."); + emitExpression(node.expression); + } + + function emitClassExpression(node: ClassExpression) { + emitClassDeclarationOrExpression(node); + } + + function emitExpressionWithTypeArguments(node: ExpressionWithTypeArguments) { + emitExpression(node.expression); + emitTypeArguments(node, node.typeArguments); + } + + function emitAsExpression(node: AsExpression) { + emitExpression(node.expression); + if (node.type) { + write(" as "); + emit(node.type); + } + } + + function emitNonNullExpression(node: NonNullExpression) { + emitExpression(node.expression); + write("!"); + } + + function emitMetaProperty(node: MetaProperty) { + writeToken(node.keywordToken, node.pos); + write("."); + emit(node.name); + } + + // + // Misc + // + + function emitTemplateSpan(node: TemplateSpan) { + emitExpression(node.expression); + emit(node.literal); + } + + // + // Statements + // + + function emitBlock(node: Block) { + if (isSingleLineEmptyBlock(node)) { + writeToken(SyntaxKind.OpenBraceToken, node.pos, /*contextNode*/ node); + write(" "); + writeToken(SyntaxKind.CloseBraceToken, node.statements.end, /*contextNode*/ node); + } + else { + writeToken(SyntaxKind.OpenBraceToken, node.pos, /*contextNode*/ node); + emitBlockStatements(node); + writeToken(SyntaxKind.CloseBraceToken, node.statements.end, /*contextNode*/ node); + } + } + + function emitBlockStatements(node: BlockLike) { + if (getEmitFlags(node) & EmitFlags.SingleLine) { + emitList(node, node.statements, ListFormat.SingleLineBlockStatements); + } + else { + emitList(node, node.statements, ListFormat.MultiLineBlockStatements); + } + } + + function emitVariableStatement(node: VariableStatement) { + emitModifiers(node, node.modifiers); + emit(node.declarationList); + write(";"); + } + + function emitEmptyStatement() { + write(";"); + } + + function emitExpressionStatement(node: ExpressionStatement) { + emitExpression(node.expression); + write(";"); + } + + function emitIfStatement(node: IfStatement) { + const openParenPos = writeToken(SyntaxKind.IfKeyword, node.pos, node); + write(" "); + writeToken(SyntaxKind.OpenParenToken, openParenPos, node); + emitExpression(node.expression); + writeToken(SyntaxKind.CloseParenToken, node.expression.end, node); + emitEmbeddedStatement(node, node.thenStatement); + if (node.elseStatement) { + writeLineOrSpace(node); + writeToken(SyntaxKind.ElseKeyword, node.thenStatement.end, node); + if (node.elseStatement.kind === SyntaxKind.IfStatement) { + write(" "); + emit(node.elseStatement); + } + else { + emitEmbeddedStatement(node, node.elseStatement); + } + } + } + + function emitDoStatement(node: DoStatement) { + write("do"); + emitEmbeddedStatement(node, node.statement); + if (isBlock(node.statement)) { + write(" "); + } + else { + writeLineOrSpace(node); + } + + write("while ("); + emitExpression(node.expression); + write(");"); + } + + function emitWhileStatement(node: WhileStatement) { + write("while ("); + emitExpression(node.expression); + write(")"); + emitEmbeddedStatement(node, node.statement); + } + + function emitForStatement(node: ForStatement) { + const openParenPos = writeToken(SyntaxKind.ForKeyword, node.pos); + write(" "); + writeToken(SyntaxKind.OpenParenToken, openParenPos, /*contextNode*/ node); + emitForBinding(node.initializer); + write(";"); + emitExpressionWithPrefix(" ", node.condition); + write(";"); + emitExpressionWithPrefix(" ", node.incrementor); + write(")"); + emitEmbeddedStatement(node, node.statement); + } + + function emitForInStatement(node: ForInStatement) { + const openParenPos = writeToken(SyntaxKind.ForKeyword, node.pos); + write(" "); + writeToken(SyntaxKind.OpenParenToken, openParenPos); + emitForBinding(node.initializer); + write(" in "); + emitExpression(node.expression); + writeToken(SyntaxKind.CloseParenToken, node.expression.end); + emitEmbeddedStatement(node, node.statement); + } + + function emitForOfStatement(node: ForOfStatement) { + const openParenPos = writeToken(SyntaxKind.ForKeyword, node.pos); + write(" "); + writeToken(SyntaxKind.OpenParenToken, openParenPos); + emitForBinding(node.initializer); + write(" of "); + emitExpression(node.expression); + writeToken(SyntaxKind.CloseParenToken, node.expression.end); + emitEmbeddedStatement(node, node.statement); + } + + function emitForBinding(node: VariableDeclarationList | Expression) { + if (node !== undefined) { + if (node.kind === SyntaxKind.VariableDeclarationList) { + emit(node); + } + else { + emitExpression(node); + } + } + } + + function emitContinueStatement(node: ContinueStatement) { + writeToken(SyntaxKind.ContinueKeyword, node.pos); + emitWithPrefix(" ", node.label); + write(";"); + } + + function emitBreakStatement(node: BreakStatement) { + writeToken(SyntaxKind.BreakKeyword, node.pos); + emitWithPrefix(" ", node.label); + write(";"); + } + + function emitReturnStatement(node: ReturnStatement) { + writeToken(SyntaxKind.ReturnKeyword, node.pos, /*contextNode*/ node); + emitExpressionWithPrefix(" ", node.expression); + write(";"); + } + + function emitWithStatement(node: WithStatement) { + write("with ("); + emitExpression(node.expression); + write(")"); + emitEmbeddedStatement(node, node.statement); + } + + function emitSwitchStatement(node: SwitchStatement) { + const openParenPos = writeToken(SyntaxKind.SwitchKeyword, node.pos); + write(" "); + writeToken(SyntaxKind.OpenParenToken, openParenPos); + emitExpression(node.expression); + writeToken(SyntaxKind.CloseParenToken, node.expression.end); + write(" "); + emit(node.caseBlock); + } + + function emitLabeledStatement(node: LabeledStatement) { + emit(node.label); + write(": "); + emit(node.statement); + } + + function emitThrowStatement(node: ThrowStatement) { + write("throw"); + emitExpressionWithPrefix(" ", node.expression); + write(";"); + } + + function emitTryStatement(node: TryStatement) { + write("try "); + emit(node.tryBlock); + if (node.catchClause) { + writeLineOrSpace(node); + emit(node.catchClause); + } + if (node.finallyBlock) { + writeLineOrSpace(node); + write("finally "); + emit(node.finallyBlock); + } + } + + function emitDebuggerStatement(node: DebuggerStatement) { + writeToken(SyntaxKind.DebuggerKeyword, node.pos); + write(";"); + } + + // + // Declarations + // + + function emitVariableDeclaration(node: VariableDeclaration) { + emit(node.name); + emitWithPrefix(": ", node.type); + emitExpressionWithPrefix(" = ", node.initializer); + } + + function emitVariableDeclarationList(node: VariableDeclarationList) { + write(isLet(node) ? "let " : isConst(node) ? "const " : "var "); + emitList(node, node.declarations, ListFormat.VariableDeclarationList); + } + + function emitFunctionDeclaration(node: FunctionDeclaration) { + emitFunctionDeclarationOrExpression(node); + } + + function emitFunctionDeclarationOrExpression(node: FunctionDeclaration | FunctionExpression) { + emitDecorators(node, node.decorators); + emitModifiers(node, node.modifiers); + write(node.asteriskToken ? "function* " : "function "); + emitIdentifierName(node.name); + emitSignatureAndBody(node, emitSignatureHead); + } + + function emitSignatureAndBody(node: FunctionLikeDeclaration, emitSignatureHead: (node: SignatureDeclaration) => void) { + const body = node.body; + if (body) { + if (isBlock(body)) { + const indentedFlag = getEmitFlags(node) & EmitFlags.Indented; + if (indentedFlag) { + increaseIndent(); + } + + if (getEmitFlags(node) & EmitFlags.ReuseTempVariableScope) { + emitSignatureHead(node); + emitBlockFunctionBody(body); + } + else { + pushNameGenerationScope(); + emitSignatureHead(node); + emitBlockFunctionBody(body); + popNameGenerationScope(); + } + + if (indentedFlag) { + decreaseIndent(); + } + } + else { + emitSignatureHead(node); + write(" "); + emitExpression(body); + } + } + else { + emitSignatureHead(node); + write(";"); + } + + } + + function emitSignatureHead(node: FunctionDeclaration | FunctionExpression | MethodDeclaration | AccessorDeclaration | ConstructorDeclaration) { + emitTypeParameters(node, node.typeParameters); + emitParameters(node, node.parameters); + emitWithPrefix(": ", node.type); + } + + function shouldEmitBlockFunctionBodyOnSingleLine(body: Block) { + // We must emit a function body as a single-line body in the following case: + // * The body has NodeEmitFlags.SingleLine specified. + + // We must emit a function body as a multi-line body in the following cases: + // * The body is explicitly marked as multi-line. + // * A non-synthesized body's start and end position are on different lines. + // * Any statement in the body starts on a new line. + + if (getEmitFlags(body) & EmitFlags.SingleLine) { + return true; + } + + if (body.multiLine) { + return false; + } + + if (!nodeIsSynthesized(body) && !rangeIsOnSingleLine(body, currentSourceFile)) { + return false; + } + + if (shouldWriteLeadingLineTerminator(body, body.statements, ListFormat.PreserveLines) + || shouldWriteClosingLineTerminator(body, body.statements, ListFormat.PreserveLines)) { + return false; + } + + let previousStatement: Statement; + for (const statement of body.statements) { + if (shouldWriteSeparatingLineTerminator(previousStatement, statement, ListFormat.PreserveLines)) { + return false; + } + + previousStatement = statement; + } + + return true; + } + + function emitBlockFunctionBody(body: Block) { + write(" {"); + increaseIndent(); + + const emitBlockFunctionBody = shouldEmitBlockFunctionBodyOnSingleLine(body) + ? emitBlockFunctionBodyOnSingleLine + : emitBlockFunctionBodyWorker; + + emitBodyIndirect(body, body.statements, emitBlockFunctionBody); + + decreaseIndent(); + writeToken(SyntaxKind.CloseBraceToken, body.statements.end, body); + } + + function emitBlockFunctionBodyOnSingleLine(body: Block) { + emitBlockFunctionBodyWorker(body, /*emitBlockFunctionBodyOnSingleLine*/ true); + } + + function emitBlockFunctionBodyWorker(body: Block, emitBlockFunctionBodyOnSingleLine?: boolean) { + // Emit all the prologue directives (like "use strict"). + const statementOffset = emitPrologueDirectives(body.statements, /*startWithNewLine*/ true); + const pos = writer.getTextPos(); + emitHelpersIndirect(body); + if (statementOffset === 0 && pos === writer.getTextPos() && emitBlockFunctionBodyOnSingleLine) { + decreaseIndent(); + emitList(body, body.statements, ListFormat.SingleLineFunctionBodyStatements); + increaseIndent(); + } + else { + emitList(body, body.statements, ListFormat.MultiLineFunctionBodyStatements, statementOffset); + } + } + + function emitClassDeclaration(node: ClassDeclaration) { + emitClassDeclarationOrExpression(node); + } + + function emitClassDeclarationOrExpression(node: ClassDeclaration | ClassExpression) { + emitDecorators(node, node.decorators); + emitModifiers(node, node.modifiers); + write("class"); + emitNodeWithPrefix(" ", node.name, emitIdentifierName); + + const indentedFlag = getEmitFlags(node) & EmitFlags.Indented; + if (indentedFlag) { + increaseIndent(); + } + + emitTypeParameters(node, node.typeParameters); + emitList(node, node.heritageClauses, ListFormat.ClassHeritageClauses); + + pushNameGenerationScope(); + write(" {"); + emitList(node, node.members, ListFormat.ClassMembers); + write("}"); + popNameGenerationScope(); + + if (indentedFlag) { + decreaseIndent(); + } + } + + function emitInterfaceDeclaration(node: InterfaceDeclaration) { + emitDecorators(node, node.decorators); + emitModifiers(node, node.modifiers); + write("interface "); + emit(node.name); + emitTypeParameters(node, node.typeParameters); + emitList(node, node.heritageClauses, ListFormat.HeritageClauses); + write(" {"); + emitList(node, node.members, ListFormat.InterfaceMembers); + write("}"); + } + + function emitTypeAliasDeclaration(node: TypeAliasDeclaration) { + emitDecorators(node, node.decorators); + emitModifiers(node, node.modifiers); + write("type "); + emit(node.name); + emitTypeParameters(node, node.typeParameters); + write(" = "); + emit(node.type); + write(";"); + } + + function emitEnumDeclaration(node: EnumDeclaration) { + emitModifiers(node, node.modifiers); + write("enum "); + emit(node.name); + pushNameGenerationScope(); + write(" {"); + emitList(node, node.members, ListFormat.EnumMembers); + write("}"); + popNameGenerationScope(); + } + + function emitModuleDeclaration(node: ModuleDeclaration) { + emitModifiers(node, node.modifiers); + write(node.flags & NodeFlags.Namespace ? "namespace " : "module "); + emit(node.name); + + let body = node.body; + while (body.kind === SyntaxKind.ModuleDeclaration) { + write("."); + emit((body).name); + body = (body).body; + } + + write(" "); + emit(body); + } + + function emitModuleBlock(node: ModuleBlock) { + if (isEmptyBlock(node)) { + write("{ }"); + } + else { + pushNameGenerationScope(); + write("{"); + increaseIndent(); + emitBlockStatements(node); + write("}"); + popNameGenerationScope(); + } + } + + function emitCaseBlock(node: CaseBlock) { + writeToken(SyntaxKind.OpenBraceToken, node.pos); + emitList(node, node.clauses, ListFormat.CaseBlockClauses); + writeToken(SyntaxKind.CloseBraceToken, node.clauses.end); + } + + function emitImportEqualsDeclaration(node: ImportEqualsDeclaration) { + emitModifiers(node, node.modifiers); + write("import "); + emit(node.name); + write(" = "); + emitModuleReference(node.moduleReference); + write(";"); + } + + function emitModuleReference(node: ModuleReference) { + if (node.kind === SyntaxKind.Identifier) { + emitExpression(node); + } + else { + emit(node); + } + } + + function emitImportDeclaration(node: ImportDeclaration) { + emitModifiers(node, node.modifiers); + write("import "); + if (node.importClause) { + emit(node.importClause); + write(" from "); + } + emitExpression(node.moduleSpecifier); + write(";"); + } + + function emitImportClause(node: ImportClause) { + emit(node.name); + if (node.name && node.namedBindings) { + write(", "); + } + emit(node.namedBindings); + } + + function emitNamespaceImport(node: NamespaceImport) { + write("* as "); + emit(node.name); + } + + function emitNamedImports(node: NamedImports) { + emitNamedImportsOrExports(node); + } + + function emitImportSpecifier(node: ImportSpecifier) { + emitImportOrExportSpecifier(node); + } + + function emitExportAssignment(node: ExportAssignment) { + write(node.isExportEquals ? "export = " : "export default "); + emitExpression(node.expression); + write(";"); + } + + function emitExportDeclaration(node: ExportDeclaration) { + write("export "); + if (node.exportClause) { + emit(node.exportClause); + } + else { + write("*"); + } + if (node.moduleSpecifier) { + write(" from "); + emitExpression(node.moduleSpecifier); + } + write(";"); + } + + function emitNamedExports(node: NamedExports) { + emitNamedImportsOrExports(node); + } + + function emitExportSpecifier(node: ExportSpecifier) { + emitImportOrExportSpecifier(node); + } + + function emitNamedImportsOrExports(node: NamedImportsOrExports) { + write("{"); + emitList(node, node.elements, ListFormat.NamedImportsOrExportsElements); + write("}"); + } + + function emitImportOrExportSpecifier(node: ImportOrExportSpecifier) { + if (node.propertyName) { + emit(node.propertyName); + write(" as "); + } + + emit(node.name); + } + + // + // Module references + // + + function emitExternalModuleReference(node: ExternalModuleReference) { + write("require("); + emitExpression(node.expression); + write(")"); + } + + // + // JSX + // + + function emitJsxElement(node: JsxElement) { + emit(node.openingElement); + emitList(node, node.children, ListFormat.JsxElementChildren); + emit(node.closingElement); + } + + function emitJsxSelfClosingElement(node: JsxSelfClosingElement) { + write("<"); + emitJsxTagName(node.tagName); + write(" "); + emitList(node, node.attributes, ListFormat.JsxElementAttributes); + write("/>"); + } + + function emitJsxOpeningElement(node: JsxOpeningElement) { + write("<"); + emitJsxTagName(node.tagName); + writeIfAny(node.attributes, " "); + emitList(node, node.attributes, ListFormat.JsxElementAttributes); + write(">"); + } + + function emitJsxText(node: JsxText) { + writer.writeLiteral(getTextOfNode(node, /*includeTrivia*/ true)); + } + + function emitJsxClosingElement(node: JsxClosingElement) { + write(""); + } + + function emitJsxAttribute(node: JsxAttribute) { + emit(node.name); + emitWithPrefix("=", node.initializer); + } + + function emitJsxSpreadAttribute(node: JsxSpreadAttribute) { + write("{..."); + emitExpression(node.expression); + write("}"); + } + + function emitJsxExpression(node: JsxExpression) { + if (node.expression) { + write("{"); + if (node.dotDotDotToken) { + write("..."); + } + emitExpression(node.expression); + write("}"); + } + } + + function emitJsxTagName(node: JsxTagNameExpression) { + if (node.kind === SyntaxKind.Identifier) { + emitExpression(node); + } + else { + emit(node); + } + } + + // + // Clauses + // + + function emitCaseClause(node: CaseClause) { + write("case "); + emitExpression(node.expression); + write(":"); + + emitCaseOrDefaultClauseStatements(node, node.statements); + } + + function emitDefaultClause(node: DefaultClause) { + write("default:"); + emitCaseOrDefaultClauseStatements(node, node.statements); + } + + function emitCaseOrDefaultClauseStatements(parentNode: Node, statements: NodeArray) { + const emitAsSingleStatement = + statements.length === 1 && + ( + // treat synthesized nodes as located on the same line for emit purposes + nodeIsSynthesized(parentNode) || + nodeIsSynthesized(statements[0]) || + rangeStartPositionsAreOnSameLine(parentNode, statements[0], currentSourceFile) + ); + + if (emitAsSingleStatement) { + write(" "); + emit(statements[0]); + } + else { + emitList(parentNode, statements, ListFormat.CaseOrDefaultClauseStatements); + } + } + + function emitHeritageClause(node: HeritageClause) { + write(" "); + writeTokenText(node.token); + write(" "); + emitList(node, node.types, ListFormat.HeritageClauseTypes); + } + + function emitCatchClause(node: CatchClause) { + writeLine(); + const openParenPos = writeToken(SyntaxKind.CatchKeyword, node.pos); + write(" "); + writeToken(SyntaxKind.OpenParenToken, openParenPos); + emit(node.variableDeclaration); + writeToken(SyntaxKind.CloseParenToken, node.variableDeclaration ? node.variableDeclaration.end : openParenPos); + write(" "); + emit(node.block); + } + + // + // Property assignments + // + + function emitPropertyAssignment(node: PropertyAssignment) { + emit(node.name); + write(": "); + // This is to ensure that we emit comment in the following case: + // For example: + // obj = { + // id: /*comment1*/ ()=>void + // } + // "comment1" is not considered to be leading comment for node.initializer + // but rather a trailing comment on the previous node. + const initializer = node.initializer; + if (emitTrailingCommentsOfPosition && (getEmitFlags(initializer) & EmitFlags.NoLeadingComments) === 0) { + const commentRange = getCommentRange(initializer); + emitTrailingCommentsOfPosition(commentRange.pos); + } + emitExpression(initializer); + } + + function emitShorthandPropertyAssignment(node: ShorthandPropertyAssignment) { + emit(node.name); + if (node.objectAssignmentInitializer) { + write(" = "); + emitExpression(node.objectAssignmentInitializer); + } + } + + function emitSpreadAssignment(node: SpreadAssignment) { + if (node.expression) { + write("..."); + emitExpression(node.expression); + } + } + + // + // Enum + // + + function emitEnumMember(node: EnumMember) { + emit(node.name); + emitExpressionWithPrefix(" = ", node.initializer); + } + + // + // Top-level nodes + // + + function emitSourceFile(node: SourceFile) { + writeLine(); + emitShebang(); + emitBodyIndirect(node, node.statements, emitSourceFileWorker); + } + + function emitSourceFileWorker(node: SourceFile) { + const statements = node.statements; + const statementOffset = emitPrologueDirectives(statements); + pushNameGenerationScope(); + emitHelpersIndirect(node); + emitList(node, statements, ListFormat.MultiLine, statementOffset); + popNameGenerationScope(); + } + + // Transformation nodes + + function emitPartiallyEmittedExpression(node: PartiallyEmittedExpression) { + emitExpression(node.expression); + } + + /** + * Emits any prologue directives at the start of a Statement list, returning the + * number of prologue directives written to the output. + */ + function emitPrologueDirectives(statements: Node[], startWithNewLine?: boolean): number { + for (let i = 0; i < statements.length; i++) { + if (isPrologueDirective(statements[i])) { + if (startWithNewLine || i > 0) { + writeLine(); + } + emit(statements[i]); + } + else { + // return index of the first non prologue directive + return i; + } + } + + return statements.length; + } + + // + // Helpers + // + + function emitShebang() { + const shebang = getShebang(currentSourceFile.text); + if (shebang) { + write(shebang); + writeLine(); + } + } + + function emitModifiers(node: Node, modifiers: NodeArray) { + if (modifiers && modifiers.length) { + emitList(node, modifiers, ListFormat.Modifiers); + write(" "); + } + } + + function emitWithPrefix(prefix: string, node: Node) { + emitNodeWithPrefix(prefix, node, emit); + } + + function emitExpressionWithPrefix(prefix: string, node: Node) { + emitNodeWithPrefix(prefix, node, emitExpression); + } + + function emitNodeWithPrefix(prefix: string, node: Node, emit: (node: Node) => void) { + if (node) { + write(prefix); + emit(node); + } + } + + function emitWithSuffix(node: Node, suffix: string) { + if (node) { + emit(node); + write(suffix); + } + } + + function emitEmbeddedStatement(parent: Node, node: Statement) { + if (isBlock(node) || getEmitFlags(parent) & EmitFlags.SingleLine) { + write(" "); + emit(node); + } + else { + writeLine(); + increaseIndent(); + emit(node); + decreaseIndent(); + } + } + + function emitDecorators(parentNode: Node, decorators: NodeArray) { + emitList(parentNode, decorators, ListFormat.Decorators); + } + + function emitTypeArguments(parentNode: Node, typeArguments: NodeArray) { + emitList(parentNode, typeArguments, ListFormat.TypeArguments); + } + + function emitTypeParameters(parentNode: Node, typeParameters: NodeArray) { + emitList(parentNode, typeParameters, ListFormat.TypeParameters); + } + + function emitParameters(parentNode: Node, parameters: NodeArray) { + emitList(parentNode, parameters, ListFormat.Parameters); + } + + function emitParametersForArrow(parentNode: Node, parameters: NodeArray) { + if (parameters && + parameters.length === 1 && + parameters[0].type === undefined && + parameters[0].pos === parentNode.pos) { + emit(parameters[0]); + } + else { + emitParameters(parentNode, parameters); + } + } + + function emitParametersForIndexSignature(parentNode: Node, parameters: NodeArray) { + emitList(parentNode, parameters, ListFormat.IndexSignatureParameters); + } + + function emitList(parentNode: Node, children: NodeArray, format: ListFormat, start?: number, count?: number) { + emitNodeList(emit, parentNode, children, format, start, count); + } + + function emitExpressionList(parentNode: Node, children: NodeArray, format: ListFormat, start?: number, count?: number) { + emitNodeList(emitExpression, parentNode, children, format, start, count); + } + + function emitNodeList(emit: (node: Node) => void, parentNode: Node, children: NodeArray, format: ListFormat, start = 0, count = children ? children.length - start : 0) { + const isUndefined = children === undefined; + if (isUndefined && format & ListFormat.OptionalIfUndefined) { + return; + } + + const isEmpty = isUndefined || children.length === 0 || start >= children.length || count === 0; + if (isEmpty && format & ListFormat.OptionalIfEmpty) { + return; + } + + if (format & ListFormat.BracketsMask) { + write(getOpeningBracket(format)); + } + + if (isEmpty) { + // Write a line terminator if the parent node was multi-line + if (format & ListFormat.MultiLine) { + writeLine(); + } + else if (format & ListFormat.SpaceBetweenBraces) { + write(" "); + } + } + else { + // Write the opening line terminator or leading whitespace. + const mayEmitInterveningComments = (format & ListFormat.NoInterveningComments) === 0; + let shouldEmitInterveningComments = mayEmitInterveningComments; + if (shouldWriteLeadingLineTerminator(parentNode, children, format)) { + writeLine(); + shouldEmitInterveningComments = false; + } + else if (format & ListFormat.SpaceBetweenBraces) { + write(" "); + } + + // Increase the indent, if requested. + if (format & ListFormat.Indented) { + increaseIndent(); + } + + // Emit each child. + let previousSibling: Node; + let shouldDecreaseIndentAfterEmit: boolean; + const delimiter = getDelimiter(format); + for (let i = 0; i < count; i++) { + const child = children[start + i]; + + // Write the delimiter if this is not the first node. + if (previousSibling) { + write(delimiter); + + // Write either a line terminator or whitespace to separate the elements. + if (shouldWriteSeparatingLineTerminator(previousSibling, child, format)) { + // If a synthesized node in a single-line list starts on a new + // line, we should increase the indent. + if ((format & (ListFormat.LinesMask | ListFormat.Indented)) === ListFormat.SingleLine) { + increaseIndent(); + shouldDecreaseIndentAfterEmit = true; + } + + writeLine(); + shouldEmitInterveningComments = false; + } + else if (previousSibling && format & ListFormat.SpaceBetweenSiblings) { + write(" "); + } + } + + // Emit this child. + if (shouldEmitInterveningComments) { + if (emitTrailingCommentsOfPosition) { + const commentRange = getCommentRange(child); + emitTrailingCommentsOfPosition(commentRange.pos); + } + } + else { + shouldEmitInterveningComments = mayEmitInterveningComments; + } + + emit(child); + + if (shouldDecreaseIndentAfterEmit) { + decreaseIndent(); + shouldDecreaseIndentAfterEmit = false; + } + + previousSibling = child; + } + + // Write a trailing comma, if requested. + const hasTrailingComma = (format & ListFormat.AllowTrailingComma) && children.hasTrailingComma; + if (format & ListFormat.CommaDelimited && hasTrailingComma) { + write(","); + } + + // Decrease the indent, if requested. + if (format & ListFormat.Indented) { + decreaseIndent(); + } + + // Write the closing line terminator or closing whitespace. + if (shouldWriteClosingLineTerminator(parentNode, children, format)) { + writeLine(); + } + else if (format & ListFormat.SpaceBetweenBraces) { + write(" "); + } + } + + if (format & ListFormat.BracketsMask) { + write(getClosingBracket(format)); + } + } + + function write(s: string) { + writer.write(s); + } + + function writeLine() { + writer.writeLine(); + } + + function increaseIndent() { + writer.increaseIndent(); + } + + function decreaseIndent() { + writer.decreaseIndent(); + } + + function writeIfAny(nodes: NodeArray, text: string) { + if (some(nodes)) { + write(text); + } + } + + function writeIfPresent(node: Node, text: string) { + if (node) { + write(text); + } + } + + function writeToken(token: SyntaxKind, pos: number, contextNode?: Node) { + return onEmitSourceMapOfToken + ? onEmitSourceMapOfToken(contextNode, token, pos, writeTokenText) + : writeTokenText(token, pos); + } + + function writeTokenText(token: SyntaxKind, pos?: number) { + const tokenString = tokenToString(token); + write(tokenString); + return pos < 0 ? pos : pos + tokenString.length; + } + + function writeLineOrSpace(node: Node) { + if (getEmitFlags(node) & EmitFlags.SingleLine) { + write(" "); + } + else { + writeLine(); + } + } + + function writeLines(text: string): void { + const lines = text.split(/\r\n?|\n/g); + const indentation = guessIndentation(lines); + for (let i = 0; i < lines.length; i++) { + const line = indentation ? lines[i].slice(indentation) : lines[i]; + if (line.length) { + writeLine(); + write(line); + writeLine(); + } + } + } + + function guessIndentation(lines: string[]) { + let indentation: number; + for (const line of lines) { + for (let i = 0; i < line.length && (indentation === undefined || i < indentation); i++) { + if (!isWhiteSpace(line.charCodeAt(i))) { + if (indentation === undefined || i < indentation) { + indentation = i; + break; + } + } + } + } + return indentation; + } + + function increaseIndentIf(value: boolean, valueToWriteWhenNotIndenting?: string) { + if (value) { + increaseIndent(); + writeLine(); + } + else if (valueToWriteWhenNotIndenting) { + write(valueToWriteWhenNotIndenting); + } + } + + // Helper function to decrease the indent if we previously indented. Allows multiple + // previous indent values to be considered at a time. This also allows caller to just + // call this once, passing in all their appropriate indent values, instead of needing + // to call this helper function multiple times. + function decreaseIndentIf(value1: boolean, value2?: boolean) { + if (value1) { + decreaseIndent(); + } + if (value2) { + decreaseIndent(); + } + } + + function shouldWriteLeadingLineTerminator(parentNode: Node, children: NodeArray, format: ListFormat) { + if (format & ListFormat.MultiLine) { + return true; + } + + if (format & ListFormat.PreserveLines) { + if (format & ListFormat.PreferNewLine) { + return true; + } + + const firstChild = children[0]; + if (firstChild === undefined) { + return !rangeIsOnSingleLine(parentNode, currentSourceFile); + } + else if (positionIsSynthesized(parentNode.pos) || nodeIsSynthesized(firstChild)) { + return synthesizedNodeStartsOnNewLine(firstChild, format); + } + else { + return !rangeStartPositionsAreOnSameLine(parentNode, firstChild, currentSourceFile); + } + } + else { + return false; + } + } + + function shouldWriteSeparatingLineTerminator(previousNode: Node, nextNode: Node, format: ListFormat) { + if (format & ListFormat.MultiLine) { + return true; + } + else if (format & ListFormat.PreserveLines) { + if (previousNode === undefined || nextNode === undefined) { + return false; + } + else if (nodeIsSynthesized(previousNode) || nodeIsSynthesized(nextNode)) { + return synthesizedNodeStartsOnNewLine(previousNode, format) || synthesizedNodeStartsOnNewLine(nextNode, format); + } + else { + return !rangeEndIsOnSameLineAsRangeStart(previousNode, nextNode, currentSourceFile); + } + } + else { + return nextNode.startsOnNewLine; + } + } + + function shouldWriteClosingLineTerminator(parentNode: Node, children: NodeArray, format: ListFormat) { + if (format & ListFormat.MultiLine) { + return (format & ListFormat.NoTrailingNewLine) === 0; + } + else if (format & ListFormat.PreserveLines) { + if (format & ListFormat.PreferNewLine) { + return true; + } + + const lastChild = lastOrUndefined(children); + if (lastChild === undefined) { + return !rangeIsOnSingleLine(parentNode, currentSourceFile); + } + else if (positionIsSynthesized(parentNode.pos) || nodeIsSynthesized(lastChild)) { + return synthesizedNodeStartsOnNewLine(lastChild, format); + } + else { + return !rangeEndPositionsAreOnSameLine(parentNode, lastChild, currentSourceFile); + } + } + else { + return false; + } + } + + function synthesizedNodeStartsOnNewLine(node: Node, format?: ListFormat) { + if (nodeIsSynthesized(node)) { + const startsOnNewLine = node.startsOnNewLine; + if (startsOnNewLine === undefined) { + return (format & ListFormat.PreferNewLine) !== 0; + } + + return startsOnNewLine; + } + + return (format & ListFormat.PreferNewLine) !== 0; + } + + function needsIndentation(parent: Node, node1: Node, node2: Node): boolean { + parent = skipSynthesizedParentheses(parent); + node1 = skipSynthesizedParentheses(node1); + node2 = skipSynthesizedParentheses(node2); + + // Always use a newline for synthesized code if the synthesizer desires it. + if (node2.startsOnNewLine) { + return true; + } + + return !nodeIsSynthesized(parent) + && !nodeIsSynthesized(node1) + && !nodeIsSynthesized(node2) + && !rangeEndIsOnSameLineAsRangeStart(node1, node2, currentSourceFile); + } + + function isSingleLineEmptyBlock(block: Block) { + return !block.multiLine + && isEmptyBlock(block); + } + + function isEmptyBlock(block: BlockLike) { + return block.statements.length === 0 + && rangeEndIsOnSameLineAsRangeStart(block, block, currentSourceFile); + } + + function skipSynthesizedParentheses(node: Node) { + while (node.kind === SyntaxKind.ParenthesizedExpression && nodeIsSynthesized(node)) { + node = (node).expression; + } + + return node; + } + + function getTextOfNode(node: Node, includeTrivia?: boolean): string { + if (isGeneratedIdentifier(node)) { + return generateName(node); + } + else if (isIdentifier(node) && (nodeIsSynthesized(node) || !node.parent)) { + return unescapeIdentifier(node.text); + } + else if (node.kind === SyntaxKind.StringLiteral && (node).textSourceNode) { + return getTextOfNode((node).textSourceNode, includeTrivia); + } + else if (isLiteralExpression(node) && (nodeIsSynthesized(node) || !node.parent)) { + return node.text; + } + + return getSourceTextOfNodeFromSourceFile(currentSourceFile, node, includeTrivia); + } + + function getLiteralTextOfNode(node: LiteralLikeNode): string { + if (node.kind === SyntaxKind.StringLiteral && (node).textSourceNode) { + const textSourceNode = (node).textSourceNode; + if (isIdentifier(textSourceNode)) { + return "\"" + escapeNonAsciiCharacters(escapeString(getTextOfNode(textSourceNode))) + "\""; + } + else { + return getLiteralTextOfNode(textSourceNode); + } + } + + return getLiteralText(node, currentSourceFile, languageVersion); + } + + /** + * Push a new name generation scope. + */ + function pushNameGenerationScope() { + tempFlagsStack.push(tempFlags); + tempFlags = 0; + } + + /** + * Pop the current name generation scope. + */ + function popNameGenerationScope() { + tempFlags = tempFlagsStack.pop(); + } + + /** + * Generate the text for a generated identifier. + */ + function generateName(name: GeneratedIdentifier) { + if (name.autoGenerateKind === GeneratedIdentifierKind.Node) { + // Node names generate unique names based on their original node + // and are cached based on that node's id. + const node = getNodeForGeneratedName(name); + return generateNameCached(node, getTextOfNode); + } + else { + // Auto, Loop, and Unique names are cached based on their unique + // autoGenerateId. + const autoGenerateId = name.autoGenerateId; + return autoGeneratedIdToGeneratedName[autoGenerateId] || (autoGeneratedIdToGeneratedName[autoGenerateId] = unescapeIdentifier(makeName(name))); + } + } + + function generateNameCached(node: Node, getTextOfNode: (node: Node, includeTrivia?: boolean) => string) { + const nodeId = getNodeId(node); + return nodeIdToGeneratedName[nodeId] || (nodeIdToGeneratedName[nodeId] = unescapeIdentifier(generateNameForNode(node, getTextOfNode))); + } + + /** + * Returns a value indicating whether a name is unique globally, within the current file, + * or within the NameGenerator. + */ + function isUniqueName(name: string): boolean { + return !(hasGlobalName && hasGlobalName(name)) + && !currentSourceFile.identifiers.has(name) + && !generatedNames.has(name); + } + + /** + * Returns a value indicating whether a name is unique within a container. + */ + function isUniqueLocalName(name: string, container: Node): boolean { + for (let node = container; isNodeDescendantOf(node, container); node = node.nextContainer) { + if (node.locals) { + const local = node.locals.get(name); + // We conservatively include alias symbols to cover cases where they're emitted as locals + if (local && local.flags & (SymbolFlags.Value | SymbolFlags.ExportValue | SymbolFlags.Alias)) { + return false; + } + } + } + return true; + } + + /** + * Return the next available name in the pattern _a ... _z, _0, _1, ... + * TempFlags._i or TempFlags._n may be used to express a preference for that dedicated name. + * Note that names generated by makeTempVariableName and makeUniqueName will never conflict. + */ + function makeTempVariableName(flags: TempFlags): string { + if (flags && !(tempFlags & flags)) { + const name = flags === TempFlags._i ? "_i" : "_n"; + if (isUniqueName(name)) { + tempFlags |= flags; + return name; + } + } + while (true) { + const count = tempFlags & TempFlags.CountMask; + tempFlags++; + // Skip over 'i' and 'n' + if (count !== 8 && count !== 13) { + const name = count < 26 + ? "_" + String.fromCharCode(CharacterCodes.a + count) + : "_" + (count - 26); + if (isUniqueName(name)) { + return name; + } + } + } + } + + /** + * Generate a name that is unique within the current file and doesn't conflict with any names + * in global scope. The name is formed by adding an '_n' suffix to the specified base name, + * where n is a positive integer. Note that names generated by makeTempVariableName and + * makeUniqueName are guaranteed to never conflict. + */ + function makeUniqueName(baseName: string): string { + // Find the first unique 'name_n', where n is a positive number + if (baseName.charCodeAt(baseName.length - 1) !== CharacterCodes._) { + baseName += "_"; + } + let i = 1; + while (true) { + const generatedName = baseName + i; + if (isUniqueName(generatedName)) { + generatedNames.set(generatedName, generatedName); + return generatedName; + } + i++; + } + } + + /** + * Generates a unique name for a ModuleDeclaration or EnumDeclaration. + */ + function generateNameForModuleOrEnum(node: ModuleDeclaration | EnumDeclaration, getTextOfNode: (node: Node, includeTrivia?: boolean) => string) { + const name = getTextOfNode(node.name); + // Use module/enum name itself if it is unique, otherwise make a unique variation + return isUniqueLocalName(name, node) ? name : makeUniqueName(name); + } + + /** + * Generates a unique name for an ImportDeclaration or ExportDeclaration. + */ + function generateNameForImportOrExportDeclaration(node: ImportDeclaration | ExportDeclaration) { + const expr = getExternalModuleName(node); + const baseName = expr.kind === SyntaxKind.StringLiteral ? + escapeIdentifier(makeIdentifierFromModuleName((expr).text)) : "module"; + return makeUniqueName(baseName); + } + + /** + * Generates a unique name for a default export. + */ + function generateNameForExportDefault() { + return makeUniqueName("default"); + } + + /** + * Generates a unique name for a class expression. + */ + function generateNameForClassExpression() { + return makeUniqueName("class"); + } + + function generateNameForMethodOrAccessor(node: MethodDeclaration | AccessorDeclaration, getTextOfNode: (node: Node, includeTrivia?: boolean) => string) { + if (isIdentifier(node.name)) { + return generateNameCached(node.name, getTextOfNode); + } + return makeTempVariableName(TempFlags.Auto); + } + + /** + * Generates a unique name from a node. + */ + function generateNameForNode(node: Node, getTextOfNode: (node: Node, includeTrivia?: boolean) => string): string { + switch (node.kind) { + case SyntaxKind.Identifier: + return makeUniqueName(getTextOfNode(node)); + case SyntaxKind.ModuleDeclaration: + case SyntaxKind.EnumDeclaration: + return generateNameForModuleOrEnum(node, getTextOfNode); + case SyntaxKind.ImportDeclaration: + case SyntaxKind.ExportDeclaration: + return generateNameForImportOrExportDeclaration(node); + case SyntaxKind.FunctionDeclaration: + case SyntaxKind.ClassDeclaration: + case SyntaxKind.ExportAssignment: + return generateNameForExportDefault(); + case SyntaxKind.ClassExpression: + return generateNameForClassExpression(); + case SyntaxKind.MethodDeclaration: + case SyntaxKind.GetAccessor: + case SyntaxKind.SetAccessor: + return generateNameForMethodOrAccessor(node, getTextOfNode); + default: + return makeTempVariableName(TempFlags.Auto); + } + } + + /** + * Generates a unique identifier for a node. + */ + function makeName(name: GeneratedIdentifier) { + switch (name.autoGenerateKind) { + case GeneratedIdentifierKind.Auto: + return makeTempVariableName(TempFlags.Auto); + case GeneratedIdentifierKind.Loop: + return makeTempVariableName(TempFlags._i); + case GeneratedIdentifierKind.Unique: + return makeUniqueName(name.text); + } + + Debug.fail("Unsupported GeneratedIdentifierKind."); + } + + /** + * Gets the node from which a name should be generated. + */ + function getNodeForGeneratedName(name: GeneratedIdentifier) { + const autoGenerateId = name.autoGenerateId; + let node = name as Node; + let original = node.original; + while (original) { + node = original; + + // if "node" is a different generated name (having a different + // "autoGenerateId"), use it and stop traversing. + if (isIdentifier(node) + && node.autoGenerateKind === GeneratedIdentifierKind.Node + && node.autoGenerateId !== autoGenerateId) { + break; + } + + original = node.original; + } + + // otherwise, return the original node for the source; + return node; + } + } + + function createDelimiterMap() { + const delimiters: string[] = []; + delimiters[ListFormat.None] = ""; + delimiters[ListFormat.CommaDelimited] = ","; + delimiters[ListFormat.BarDelimited] = " |"; + delimiters[ListFormat.AmpersandDelimited] = " &"; + return delimiters; + } + + function getDelimiter(format: ListFormat) { + return delimiters[format & ListFormat.DelimitersMask]; + } + + function createBracketsMap() { + const brackets: string[][] = []; + brackets[ListFormat.Braces] = ["{", "}"]; + brackets[ListFormat.Parenthesis] = ["(", ")"]; + brackets[ListFormat.AngleBrackets] = ["<", ">"]; + brackets[ListFormat.SquareBrackets] = ["[", "]"]; + return brackets; + } + + function getOpeningBracket(format: ListFormat) { + return brackets[format & ListFormat.BracketsMask][0]; + } + + function getClosingBracket(format: ListFormat) { + return brackets[format & ListFormat.BracketsMask][1]; + } + + // Flags enum to track count of temp variables and a few dedicated names + const enum TempFlags { + Auto = 0x00000000, // No preferred name + CountMask = 0x0FFFFFFF, // Temp variable counter + _i = 0x10000000, // Use/preference flag for '_i' + } + + const enum ListFormat { + None = 0, + + // Line separators + SingleLine = 0, // Prints the list on a single line (default). + MultiLine = 1 << 0, // Prints the list on multiple lines. + PreserveLines = 1 << 1, // Prints the list using line preservation if possible. + LinesMask = SingleLine | MultiLine | PreserveLines, + + // Delimiters + NotDelimited = 0, // There is no delimiter between list items (default). + BarDelimited = 1 << 2, // Each list item is space-and-bar (" |") delimited. + AmpersandDelimited = 1 << 3, // Each list item is space-and-ampersand (" &") delimited. + CommaDelimited = 1 << 4, // Each list item is comma (",") delimited. + DelimitersMask = BarDelimited | AmpersandDelimited | CommaDelimited, + + AllowTrailingComma = 1 << 5, // Write a trailing comma (",") if present. + + // Whitespace + Indented = 1 << 6, // The list should be indented. + SpaceBetweenBraces = 1 << 7, // Inserts a space after the opening brace and before the closing brace. + SpaceBetweenSiblings = 1 << 8, // Inserts a space between each sibling node. + + // Brackets/Braces + Braces = 1 << 9, // The list is surrounded by "{" and "}". + Parenthesis = 1 << 10, // The list is surrounded by "(" and ")". + AngleBrackets = 1 << 11, // The list is surrounded by "<" and ">". + SquareBrackets = 1 << 12, // The list is surrounded by "[" and "]". + BracketsMask = Braces | Parenthesis | AngleBrackets | SquareBrackets, + + OptionalIfUndefined = 1 << 13, // Do not emit brackets if the list is undefined. + OptionalIfEmpty = 1 << 14, // Do not emit brackets if the list is empty. + Optional = OptionalIfUndefined | OptionalIfEmpty, + + // Other + PreferNewLine = 1 << 15, // Prefer adding a LineTerminator between synthesized nodes. + NoTrailingNewLine = 1 << 16, // Do not emit a trailing NewLine for a MultiLine list. + NoInterveningComments = 1 << 17, // Do not emit comments between each node + + // Precomputed Formats + Modifiers = SingleLine | SpaceBetweenSiblings, + HeritageClauses = SingleLine | SpaceBetweenSiblings, + TypeLiteralMembers = MultiLine | Indented, + TupleTypeElements = CommaDelimited | SpaceBetweenSiblings | SingleLine | Indented, + UnionTypeConstituents = BarDelimited | SpaceBetweenSiblings | SingleLine, + IntersectionTypeConstituents = AmpersandDelimited | SpaceBetweenSiblings | SingleLine, + ObjectBindingPatternElements = SingleLine | AllowTrailingComma | SpaceBetweenBraces | CommaDelimited | SpaceBetweenSiblings, + ArrayBindingPatternElements = SingleLine | AllowTrailingComma | CommaDelimited | SpaceBetweenSiblings, + ObjectLiteralExpressionProperties = PreserveLines | CommaDelimited | SpaceBetweenSiblings | SpaceBetweenBraces | Indented | Braces, + ArrayLiteralExpressionElements = PreserveLines | CommaDelimited | SpaceBetweenSiblings | AllowTrailingComma | Indented | SquareBrackets, + CallExpressionArguments = CommaDelimited | SpaceBetweenSiblings | SingleLine | Parenthesis, + NewExpressionArguments = CommaDelimited | SpaceBetweenSiblings | SingleLine | Parenthesis | OptionalIfUndefined, + TemplateExpressionSpans = SingleLine | NoInterveningComments, + SingleLineBlockStatements = SpaceBetweenBraces | SpaceBetweenSiblings | SingleLine, + MultiLineBlockStatements = Indented | MultiLine, + VariableDeclarationList = CommaDelimited | SpaceBetweenSiblings | SingleLine, + SingleLineFunctionBodyStatements = SingleLine | SpaceBetweenSiblings | SpaceBetweenBraces, + MultiLineFunctionBodyStatements = MultiLine, + ClassHeritageClauses = SingleLine | SpaceBetweenSiblings, + ClassMembers = Indented | MultiLine, + InterfaceMembers = Indented | MultiLine, + EnumMembers = CommaDelimited | Indented | MultiLine, + CaseBlockClauses = Indented | MultiLine, + NamedImportsOrExportsElements = CommaDelimited | SpaceBetweenSiblings | AllowTrailingComma | SingleLine | SpaceBetweenBraces, + JsxElementChildren = SingleLine | NoInterveningComments, + JsxElementAttributes = SingleLine | SpaceBetweenSiblings | NoInterveningComments, + CaseOrDefaultClauseStatements = Indented | MultiLine | NoTrailingNewLine | OptionalIfEmpty, + HeritageClauseTypes = CommaDelimited | SpaceBetweenSiblings | SingleLine, + SourceFileStatements = MultiLine | NoTrailingNewLine, + Decorators = MultiLine | Optional, + TypeArguments = CommaDelimited | SpaceBetweenSiblings | SingleLine | Indented | AngleBrackets | Optional, + TypeParameters = CommaDelimited | SpaceBetweenSiblings | SingleLine | Indented | AngleBrackets | Optional, + Parameters = CommaDelimited | SpaceBetweenSiblings | SingleLine | Indented | Parenthesis, + IndexSignatureParameters = CommaDelimited | SpaceBetweenSiblings | SingleLine | Indented | SquareBrackets, + } } \ No newline at end of file diff --git a/src/compiler/printer.ts b/src/compiler/printer.ts deleted file mode 100644 index 9ae824dac67..00000000000 --- a/src/compiler/printer.ts +++ /dev/null @@ -1,2659 +0,0 @@ -/// - -namespace ts { - // Flags enum to track count of temp variables and a few dedicated names - const enum TempFlags { - Auto = 0x00000000, // No preferred name - CountMask = 0x0FFFFFFF, // Temp variable counter - _i = 0x10000000, // Use/preference flag for '_i' - } - - const delimiters = createDelimiterMap(); - const brackets = createBracketsMap(); - - export function createPrinter(writer: EmitTextWriter, compilerOptions: CompilerOptions, printerOptions: PrinterOptions = {}): Printer { - const languageVersion = getEmitScriptTarget(compilerOptions); - const moduleKind = getEmitModuleKind(compilerOptions); - const { - hasGlobalName, - onEmitSourceMapOfNode, - onEmitSourceMapOfToken, - onEmitCommentsOfNode, - onEmitDetachedCommentsOfNode, - onEmitTrailingCommentsOfPosition, - onEmitNode, - onEmitHelpers, - onSetSourceFile, - onSubstituteNode, - } = printerOptions; - const { - write, - writeLine, - increaseIndent, - decreaseIndent - } = writer; - - let currentSourceFile: SourceFile; - let nodeIdToGeneratedName: string[]; // Map of generated names for specific nodes. - let autoGeneratedIdToGeneratedName: string[]; // Map of generated names for temp and loop variables. - let generatedNames: Map; // Set of names generated by the NameGenerator. - let tempFlagsStack: TempFlags[]; // Stack of enclosing name generation scopes. - let tempFlags: TempFlags; // TempFlags for the current name generation scope. - - return { - printNode, - printFile, - printBundle - }; - - function printNode(hint: EmitHint, node: Node, sourceFile: SourceFile) { - print(hint, node, sourceFile); - resetGeneratedNames(); - } - - function printBundle(bundle: Bundle) { - if (moduleKind) { - emitHelpersIndirect(bundle); - } - for (const sourceFile of bundle.sourceFiles) { - print(EmitHint.SourceFile, sourceFile, sourceFile); - } - resetGeneratedNames(); - } - - function printFile(sourceFile: SourceFile) { - print(EmitHint.SourceFile, sourceFile, sourceFile); - resetGeneratedNames(); - } - - function print(hint: EmitHint, node: Node, sourceFile: SourceFile) { - setSourceFile(sourceFile); - pipelineEmitWithNotification(hint, node); - } - - function setSourceFile(sourceFile: SourceFile) { - currentSourceFile = sourceFile; - - if (onSetSourceFile) { - onSetSourceFile(sourceFile); - } - } - - function emit(node: Node, hint = EmitHint.Unspecified) { - pipelineEmitWithNotification(hint, node); - } - - function emitIdentifierName(node: Identifier) { - pipelineEmitWithNotification(EmitHint.IdentifierName, node); - } - - function emitExpression(node: Expression) { - pipelineEmitWithNotification(EmitHint.Expression, node); - } - - function pipelineEmitWithNotification(hint: EmitHint, node: Node) { - if (onEmitNode) { - onEmitNode(hint, node, pipelineEmitWithComments); - } - else { - pipelineEmitWithComments(hint, node); - } - } - - function pipelineEmitWithComments(hint: EmitHint, node: Node) { - if (onEmitCommentsOfNode && hint !== EmitHint.SourceFile) { - onEmitCommentsOfNode(hint, node, pipelineEmitWithSourceMap); - } - else { - pipelineEmitWithSourceMap(hint, node); - } - } - - function pipelineEmitWithSourceMap(hint: EmitHint, node: Node) { - if (onEmitSourceMapOfNode && hint !== EmitHint.SourceFile && hint !== EmitHint.IdentifierName) { - onEmitSourceMapOfNode(hint, node, pipelineEmitWithSubstitution); - } - else { - pipelineEmitWithSubstitution(hint, node); - } - } - - function pipelineEmitWithSubstitution(hint: EmitHint, node: Node) { - if (onSubstituteNode) { - onSubstituteNode(hint, node, pipelineEmitWithHint); - } - else { - pipelineEmitWithHint(hint, node); - } - } - - function pipelineEmitWithHint(hint: EmitHint, node: Node): void { - switch (hint) { - case EmitHint.SourceFile: return pipelineEmitSourceFile(node); - case EmitHint.IdentifierName: return pipelineEmitIdentifierName(node); - case EmitHint.Expression: return pipelineEmitExpression(node); - case EmitHint.Unspecified: return pipelineEmitUnspecified(node); - } - } - - function pipelineEmitSourceFile(node: Node): void { - Debug.assertNode(node, isSourceFile); - emitSourceFile(node); - } - - function pipelineEmitIdentifierName(node: Node): void { - Debug.assertNode(node, isIdentifier); - emitIdentifier(node); - } - - function pipelineEmitUnspecified(node: Node): void { - const kind = node.kind; - switch (kind) { - // Pseudo-literals - case SyntaxKind.TemplateHead: - case SyntaxKind.TemplateMiddle: - case SyntaxKind.TemplateTail: - return emitLiteral(node); - - // Identifiers - case SyntaxKind.Identifier: - return emitIdentifier(node); - - // Reserved words - case SyntaxKind.ConstKeyword: - case SyntaxKind.DefaultKeyword: - case SyntaxKind.ExportKeyword: - case SyntaxKind.VoidKeyword: - - // Strict mode reserved words - case SyntaxKind.PrivateKeyword: - case SyntaxKind.ProtectedKeyword: - case SyntaxKind.PublicKeyword: - case SyntaxKind.StaticKeyword: - - // Contextual keywords - case SyntaxKind.AbstractKeyword: - case SyntaxKind.AsKeyword: - case SyntaxKind.AnyKeyword: - case SyntaxKind.AsyncKeyword: - case SyntaxKind.AwaitKeyword: - case SyntaxKind.BooleanKeyword: - case SyntaxKind.ConstructorKeyword: - case SyntaxKind.DeclareKeyword: - case SyntaxKind.GetKeyword: - case SyntaxKind.IsKeyword: - case SyntaxKind.ModuleKeyword: - case SyntaxKind.NamespaceKeyword: - case SyntaxKind.NeverKeyword: - case SyntaxKind.ReadonlyKeyword: - case SyntaxKind.RequireKeyword: - case SyntaxKind.NumberKeyword: - case SyntaxKind.SetKeyword: - case SyntaxKind.StringKeyword: - case SyntaxKind.SymbolKeyword: - case SyntaxKind.TypeKeyword: - case SyntaxKind.UndefinedKeyword: - case SyntaxKind.FromKeyword: - case SyntaxKind.GlobalKeyword: - case SyntaxKind.OfKeyword: - writeTokenText(kind); - return; - - // Parse tree nodes - - // Names - case SyntaxKind.QualifiedName: - return emitQualifiedName(node); - case SyntaxKind.ComputedPropertyName: - return emitComputedPropertyName(node); - - // Signature elements - case SyntaxKind.TypeParameter: - return emitTypeParameter(node); - case SyntaxKind.Parameter: - return emitParameter(node); - case SyntaxKind.Decorator: - return emitDecorator(node); - - // Type members - case SyntaxKind.PropertySignature: - return emitPropertySignature(node); - case SyntaxKind.PropertyDeclaration: - return emitPropertyDeclaration(node); - case SyntaxKind.MethodSignature: - return emitMethodSignature(node); - case SyntaxKind.MethodDeclaration: - return emitMethodDeclaration(node); - case SyntaxKind.Constructor: - return emitConstructor(node); - case SyntaxKind.GetAccessor: - case SyntaxKind.SetAccessor: - return emitAccessorDeclaration(node); - case SyntaxKind.CallSignature: - return emitCallSignature(node); - case SyntaxKind.ConstructSignature: - return emitConstructSignature(node); - case SyntaxKind.IndexSignature: - return emitIndexSignature(node); - - // Types - case SyntaxKind.TypePredicate: - return emitTypePredicate(node); - case SyntaxKind.TypeReference: - return emitTypeReference(node); - case SyntaxKind.FunctionType: - return emitFunctionType(node); - case SyntaxKind.ConstructorType: - return emitConstructorType(node); - case SyntaxKind.TypeQuery: - return emitTypeQuery(node); - case SyntaxKind.TypeLiteral: - return emitTypeLiteral(node); - case SyntaxKind.ArrayType: - return emitArrayType(node); - case SyntaxKind.TupleType: - return emitTupleType(node); - case SyntaxKind.UnionType: - return emitUnionType(node); - case SyntaxKind.IntersectionType: - return emitIntersectionType(node); - case SyntaxKind.ParenthesizedType: - return emitParenthesizedType(node); - case SyntaxKind.ExpressionWithTypeArguments: - return emitExpressionWithTypeArguments(node); - case SyntaxKind.ThisType: - return emitThisType(); - case SyntaxKind.TypeOperator: - return emitTypeOperator(node); - case SyntaxKind.IndexedAccessType: - return emitIndexedAccessType(node); - case SyntaxKind.MappedType: - return emitMappedType(node); - case SyntaxKind.LiteralType: - return emitLiteralType(node); - - // Binding patterns - case SyntaxKind.ObjectBindingPattern: - return emitObjectBindingPattern(node); - case SyntaxKind.ArrayBindingPattern: - return emitArrayBindingPattern(node); - case SyntaxKind.BindingElement: - return emitBindingElement(node); - - // Misc - case SyntaxKind.TemplateSpan: - return emitTemplateSpan(node); - case SyntaxKind.SemicolonClassElement: - return emitSemicolonClassElement(); - - // Statements - case SyntaxKind.Block: - return emitBlock(node); - case SyntaxKind.VariableStatement: - return emitVariableStatement(node); - case SyntaxKind.EmptyStatement: - return emitEmptyStatement(); - case SyntaxKind.ExpressionStatement: - return emitExpressionStatement(node); - case SyntaxKind.IfStatement: - return emitIfStatement(node); - case SyntaxKind.DoStatement: - return emitDoStatement(node); - case SyntaxKind.WhileStatement: - return emitWhileStatement(node); - case SyntaxKind.ForStatement: - return emitForStatement(node); - case SyntaxKind.ForInStatement: - return emitForInStatement(node); - case SyntaxKind.ForOfStatement: - return emitForOfStatement(node); - case SyntaxKind.ContinueStatement: - return emitContinueStatement(node); - case SyntaxKind.BreakStatement: - return emitBreakStatement(node); - case SyntaxKind.ReturnStatement: - return emitReturnStatement(node); - case SyntaxKind.WithStatement: - return emitWithStatement(node); - case SyntaxKind.SwitchStatement: - return emitSwitchStatement(node); - case SyntaxKind.LabeledStatement: - return emitLabeledStatement(node); - case SyntaxKind.ThrowStatement: - return emitThrowStatement(node); - case SyntaxKind.TryStatement: - return emitTryStatement(node); - case SyntaxKind.DebuggerStatement: - return emitDebuggerStatement(node); - - // Declarations - case SyntaxKind.VariableDeclaration: - return emitVariableDeclaration(node); - case SyntaxKind.VariableDeclarationList: - return emitVariableDeclarationList(node); - case SyntaxKind.FunctionDeclaration: - return emitFunctionDeclaration(node); - case SyntaxKind.ClassDeclaration: - return emitClassDeclaration(node); - case SyntaxKind.InterfaceDeclaration: - return emitInterfaceDeclaration(node); - case SyntaxKind.TypeAliasDeclaration: - return emitTypeAliasDeclaration(node); - case SyntaxKind.EnumDeclaration: - return emitEnumDeclaration(node); - case SyntaxKind.ModuleDeclaration: - return emitModuleDeclaration(node); - case SyntaxKind.ModuleBlock: - return emitModuleBlock(node); - case SyntaxKind.CaseBlock: - return emitCaseBlock(node); - case SyntaxKind.ImportEqualsDeclaration: - return emitImportEqualsDeclaration(node); - case SyntaxKind.ImportDeclaration: - return emitImportDeclaration(node); - case SyntaxKind.ImportClause: - return emitImportClause(node); - case SyntaxKind.NamespaceImport: - return emitNamespaceImport(node); - case SyntaxKind.NamedImports: - return emitNamedImports(node); - case SyntaxKind.ImportSpecifier: - return emitImportSpecifier(node); - case SyntaxKind.ExportAssignment: - return emitExportAssignment(node); - case SyntaxKind.ExportDeclaration: - return emitExportDeclaration(node); - case SyntaxKind.NamedExports: - return emitNamedExports(node); - case SyntaxKind.ExportSpecifier: - return emitExportSpecifier(node); - case SyntaxKind.MissingDeclaration: - return; - - // Module references - case SyntaxKind.ExternalModuleReference: - return emitExternalModuleReference(node); - - // JSX (non-expression) - case SyntaxKind.JsxText: - return emitJsxText(node); - case SyntaxKind.JsxOpeningElement: - return emitJsxOpeningElement(node); - case SyntaxKind.JsxClosingElement: - return emitJsxClosingElement(node); - case SyntaxKind.JsxAttribute: - return emitJsxAttribute(node); - case SyntaxKind.JsxSpreadAttribute: - return emitJsxSpreadAttribute(node); - case SyntaxKind.JsxExpression: - return emitJsxExpression(node); - - // Clauses - case SyntaxKind.CaseClause: - return emitCaseClause(node); - case SyntaxKind.DefaultClause: - return emitDefaultClause(node); - case SyntaxKind.HeritageClause: - return emitHeritageClause(node); - case SyntaxKind.CatchClause: - return emitCatchClause(node); - - // Property assignments - case SyntaxKind.PropertyAssignment: - return emitPropertyAssignment(node); - case SyntaxKind.ShorthandPropertyAssignment: - return emitShorthandPropertyAssignment(node); - case SyntaxKind.SpreadAssignment: - return emitSpreadAssignment(node as SpreadAssignment); - - // Enum - case SyntaxKind.EnumMember: - return emitEnumMember(node); - - // JSDoc nodes (ignored) - // Transformation nodes (ignored) - } - - // If the node is an expression, try to emit it as an expression with - // substitution. - if (isExpression(node)) { - return pipelineEmitWithSubstitution(EmitHint.Expression, node); - } - } - - function pipelineEmitExpression(node: Node): void { - const kind = node.kind; - switch (kind) { - // Literals - case SyntaxKind.NumericLiteral: - return emitNumericLiteral(node); - - case SyntaxKind.StringLiteral: - case SyntaxKind.RegularExpressionLiteral: - case SyntaxKind.NoSubstitutionTemplateLiteral: - return emitLiteral(node); - - // Identifiers - case SyntaxKind.Identifier: - return emitIdentifier(node); - - // Reserved words - case SyntaxKind.FalseKeyword: - case SyntaxKind.NullKeyword: - case SyntaxKind.SuperKeyword: - case SyntaxKind.TrueKeyword: - case SyntaxKind.ThisKeyword: - writeTokenText(kind); - return; - - // Expressions - case SyntaxKind.ArrayLiteralExpression: - return emitArrayLiteralExpression(node); - case SyntaxKind.ObjectLiteralExpression: - return emitObjectLiteralExpression(node); - case SyntaxKind.PropertyAccessExpression: - return emitPropertyAccessExpression(node); - case SyntaxKind.ElementAccessExpression: - return emitElementAccessExpression(node); - case SyntaxKind.CallExpression: - return emitCallExpression(node); - case SyntaxKind.NewExpression: - return emitNewExpression(node); - case SyntaxKind.TaggedTemplateExpression: - return emitTaggedTemplateExpression(node); - case SyntaxKind.TypeAssertionExpression: - return emitTypeAssertionExpression(node); - case SyntaxKind.ParenthesizedExpression: - return emitParenthesizedExpression(node); - case SyntaxKind.FunctionExpression: - return emitFunctionExpression(node); - case SyntaxKind.ArrowFunction: - return emitArrowFunction(node); - case SyntaxKind.DeleteExpression: - return emitDeleteExpression(node); - case SyntaxKind.TypeOfExpression: - return emitTypeOfExpression(node); - case SyntaxKind.VoidExpression: - return emitVoidExpression(node); - case SyntaxKind.AwaitExpression: - return emitAwaitExpression(node); - case SyntaxKind.PrefixUnaryExpression: - return emitPrefixUnaryExpression(node); - case SyntaxKind.PostfixUnaryExpression: - return emitPostfixUnaryExpression(node); - case SyntaxKind.BinaryExpression: - return emitBinaryExpression(node); - case SyntaxKind.ConditionalExpression: - return emitConditionalExpression(node); - case SyntaxKind.TemplateExpression: - return emitTemplateExpression(node); - case SyntaxKind.YieldExpression: - return emitYieldExpression(node); - case SyntaxKind.SpreadElement: - return emitSpreadExpression(node); - case SyntaxKind.ClassExpression: - return emitClassExpression(node); - case SyntaxKind.OmittedExpression: - return; - case SyntaxKind.AsExpression: - return emitAsExpression(node); - case SyntaxKind.NonNullExpression: - return emitNonNullExpression(node); - case SyntaxKind.MetaProperty: - return emitMetaProperty(node); - - // JSX - case SyntaxKind.JsxElement: - return emitJsxElement(node); - case SyntaxKind.JsxSelfClosingElement: - return emitJsxSelfClosingElement(node); - - // Transformation nodes - case SyntaxKind.PartiallyEmittedExpression: - return emitPartiallyEmittedExpression(node); - } - } - - function emitBodyIndirect(node: Node, elements: NodeArray, emitCallback: (node: Node) => void): void { - if (onEmitDetachedCommentsOfNode) { - onEmitDetachedCommentsOfNode(node, elements, emitCallback); - } - else { - emitCallback(node); - } - } - - function emitHelpersIndirect(node: Node) { - if (onEmitHelpers) { - onEmitHelpers(node, writeLines); - } - } - - // - // Literals/Pseudo-literals - // - - // SyntaxKind.NumericLiteral - function emitNumericLiteral(node: NumericLiteral) { - emitLiteral(node); - if (node.trailingComment) { - write(` /*${node.trailingComment}*/`); - } - } - - // SyntaxKind.StringLiteral - // SyntaxKind.RegularExpressionLiteral - // SyntaxKind.NoSubstitutionTemplateLiteral - // SyntaxKind.TemplateHead - // SyntaxKind.TemplateMiddle - // SyntaxKind.TemplateTail - function emitLiteral(node: LiteralLikeNode) { - const text = getLiteralTextOfNode(node); - if ((compilerOptions.sourceMap || compilerOptions.inlineSourceMap) - && (node.kind === SyntaxKind.StringLiteral || isTemplateLiteralKind(node.kind))) { - writer.writeLiteral(text); - } - else { - write(text); - } - } - - // - // Identifiers - // - - function emitIdentifier(node: Identifier) { - write(getTextOfNode(node, /*includeTrivia*/ false)); - } - - // - // Names - // - - function emitQualifiedName(node: QualifiedName) { - emitEntityName(node.left); - write("."); - emit(node.right); - } - - function emitEntityName(node: EntityName) { - if (node.kind === SyntaxKind.Identifier) { - emitExpression(node); - } - else { - emit(node); - } - } - - function emitComputedPropertyName(node: ComputedPropertyName) { - write("["); - emitExpression(node.expression); - write("]"); - } - - // - // Signature elements - // - - function emitTypeParameter(node: TypeParameterDeclaration) { - emit(node.name); - emitWithPrefix(" extends ", node.constraint); - } - - function emitParameter(node: ParameterDeclaration) { - emitDecorators(node, node.decorators); - emitModifiers(node, node.modifiers); - writeIfPresent(node.dotDotDotToken, "..."); - emit(node.name); - writeIfPresent(node.questionToken, "?"); - emitExpressionWithPrefix(" = ", node.initializer); - emitWithPrefix(": ", node.type); - } - - function emitDecorator(decorator: Decorator) { - write("@"); - emitExpression(decorator.expression); - } - - // - // Type members - // - - function emitPropertySignature(node: PropertySignature) { - emitDecorators(node, node.decorators); - emitModifiers(node, node.modifiers); - emit(node.name); - writeIfPresent(node.questionToken, "?"); - emitWithPrefix(": ", node.type); - write(";"); - } - - function emitPropertyDeclaration(node: PropertyDeclaration) { - emitDecorators(node, node.decorators); - emitModifiers(node, node.modifiers); - emit(node.name); - emitWithPrefix(": ", node.type); - emitExpressionWithPrefix(" = ", node.initializer); - write(";"); - } - - function emitMethodSignature(node: MethodSignature) { - emitDecorators(node, node.decorators); - emitModifiers(node, node.modifiers); - emit(node.name); - writeIfPresent(node.questionToken, "?"); - emitTypeParameters(node, node.typeParameters); - emitParameters(node, node.parameters); - emitWithPrefix(": ", node.type); - write(";"); - } - - function emitMethodDeclaration(node: MethodDeclaration) { - emitDecorators(node, node.decorators); - emitModifiers(node, node.modifiers); - writeIfPresent(node.asteriskToken, "*"); - emit(node.name); - emitSignatureAndBody(node, emitSignatureHead); - } - - function emitConstructor(node: ConstructorDeclaration) { - emitModifiers(node, node.modifiers); - write("constructor"); - emitSignatureAndBody(node, emitSignatureHead); - } - - function emitAccessorDeclaration(node: AccessorDeclaration) { - emitDecorators(node, node.decorators); - emitModifiers(node, node.modifiers); - write(node.kind === SyntaxKind.GetAccessor ? "get " : "set "); - emit(node.name); - emitSignatureAndBody(node, emitSignatureHead); - } - - function emitCallSignature(node: CallSignatureDeclaration) { - emitDecorators(node, node.decorators); - emitModifiers(node, node.modifiers); - emitTypeParameters(node, node.typeParameters); - emitParameters(node, node.parameters); - emitWithPrefix(": ", node.type); - write(";"); - } - - function emitConstructSignature(node: ConstructSignatureDeclaration) { - emitDecorators(node, node.decorators); - emitModifiers(node, node.modifiers); - write("new "); - emitTypeParameters(node, node.typeParameters); - emitParameters(node, node.parameters); - emitWithPrefix(": ", node.type); - write(";"); - } - - function emitIndexSignature(node: IndexSignatureDeclaration) { - emitDecorators(node, node.decorators); - emitModifiers(node, node.modifiers); - emitParametersForIndexSignature(node, node.parameters); - emitWithPrefix(": ", node.type); - write(";"); - } - - function emitSemicolonClassElement() { - write(";"); - } - - // - // Types - // - - function emitTypePredicate(node: TypePredicateNode) { - emit(node.parameterName); - write(" is "); - emit(node.type); - } - - function emitTypeReference(node: TypeReferenceNode) { - emit(node.typeName); - emitTypeArguments(node, node.typeArguments); - } - - function emitFunctionType(node: FunctionTypeNode) { - emitTypeParameters(node, node.typeParameters); - emitParametersForArrow(node, node.parameters); - write(" => "); - emit(node.type); - } - - function emitConstructorType(node: ConstructorTypeNode) { - write("new "); - emitTypeParameters(node, node.typeParameters); - emitParametersForArrow(node, node.parameters); - write(" => "); - emit(node.type); - } - - function emitTypeQuery(node: TypeQueryNode) { - write("typeof "); - emit(node.exprName); - } - - function emitTypeLiteral(node: TypeLiteralNode) { - write("{"); - emitList(node, node.members, ListFormat.TypeLiteralMembers); - write("}"); - } - - function emitArrayType(node: ArrayTypeNode) { - emit(node.elementType); - write("[]"); - } - - function emitTupleType(node: TupleTypeNode) { - write("["); - emitList(node, node.elementTypes, ListFormat.TupleTypeElements); - write("]"); - } - - function emitUnionType(node: UnionTypeNode) { - emitList(node, node.types, ListFormat.UnionTypeConstituents); - } - - function emitIntersectionType(node: IntersectionTypeNode) { - emitList(node, node.types, ListFormat.IntersectionTypeConstituents); - } - - function emitParenthesizedType(node: ParenthesizedTypeNode) { - write("("); - emit(node.type); - write(")"); - } - - function emitThisType() { - write("this"); - } - - function emitTypeOperator(node: TypeOperatorNode) { - writeTokenText(node.operator); - write(" "); - emit(node.type); - } - - function emitIndexedAccessType(node: IndexedAccessTypeNode) { - emit(node.objectType); - write("["); - emit(node.indexType); - write("]"); - } - - function emitMappedType(node: MappedTypeNode) { - write("{"); - writeLine(); - increaseIndent(); - writeIfPresent(node.readonlyToken, "readonly "); - write("["); - emit(node.typeParameter.name); - write(" in "); - emit(node.typeParameter.constraint); - write("]"); - writeIfPresent(node.questionToken, "?"); - write(": "); - emit(node.type); - write(";"); - writeLine(); - decreaseIndent(); - write("}"); - } - - function emitLiteralType(node: LiteralTypeNode) { - emitExpression(node.literal); - } - - // - // Binding patterns - // - - function emitObjectBindingPattern(node: ObjectBindingPattern) { - const elements = node.elements; - if (elements.length === 0) { - write("{}"); - } - else { - write("{"); - emitList(node, elements, ListFormat.ObjectBindingPatternElements); - write("}"); - } - } - - function emitArrayBindingPattern(node: ArrayBindingPattern) { - const elements = node.elements; - if (elements.length === 0) { - write("[]"); - } - else { - write("["); - emitList(node, node.elements, ListFormat.ArrayBindingPatternElements); - write("]"); - } - } - - function emitBindingElement(node: BindingElement) { - emitWithSuffix(node.propertyName, ": "); - writeIfPresent(node.dotDotDotToken, "..."); - emit(node.name); - emitExpressionWithPrefix(" = ", node.initializer); - } - - // - // Expressions - // - - function emitArrayLiteralExpression(node: ArrayLiteralExpression) { - const elements = node.elements; - if (elements.length === 0) { - write("[]"); - } - else { - const preferNewLine = node.multiLine ? ListFormat.PreferNewLine : ListFormat.None; - emitExpressionList(node, elements, ListFormat.ArrayLiteralExpressionElements | preferNewLine); - } - } - - function emitObjectLiteralExpression(node: ObjectLiteralExpression) { - const properties = node.properties; - if (properties.length === 0) { - write("{}"); - } - else { - const indentedFlag = getEmitFlags(node) & EmitFlags.Indented; - if (indentedFlag) { - increaseIndent(); - } - - const preferNewLine = node.multiLine ? ListFormat.PreferNewLine : ListFormat.None; - const allowTrailingComma = languageVersion >= ScriptTarget.ES5 ? ListFormat.AllowTrailingComma : ListFormat.None; - emitList(node, properties, ListFormat.ObjectLiteralExpressionProperties | allowTrailingComma | preferNewLine); - - if (indentedFlag) { - decreaseIndent(); - } - } - } - - function emitPropertyAccessExpression(node: PropertyAccessExpression) { - let indentBeforeDot = false; - let indentAfterDot = false; - if (!(getEmitFlags(node) & EmitFlags.NoIndentation)) { - const dotRangeStart = node.expression.end; - const dotRangeEnd = skipTrivia(currentSourceFile.text, node.expression.end) + 1; - const dotToken = { kind: SyntaxKind.DotToken, pos: dotRangeStart, end: dotRangeEnd }; - indentBeforeDot = needsIndentation(node, node.expression, dotToken); - indentAfterDot = needsIndentation(node, dotToken, node.name); - } - - emitExpression(node.expression); - increaseIndentIf(indentBeforeDot); - - const shouldEmitDotDot = !indentBeforeDot && needsDotDotForPropertyAccess(node.expression); - write(shouldEmitDotDot ? ".." : "."); - - increaseIndentIf(indentAfterDot); - emit(node.name); - decreaseIndentIf(indentBeforeDot, indentAfterDot); - } - - // 1..toString is a valid property access, emit a dot after the literal - // Also emit a dot if expression is a integer const enum value - it will appear in generated code as numeric literal - function needsDotDotForPropertyAccess(expression: Expression) { - if (expression.kind === SyntaxKind.NumericLiteral) { - // check if numeric literal is a decimal literal that was originally written with a dot - const text = getLiteralTextOfNode(expression); - return getNumericLiteralFlags(text, /*hint*/ NumericLiteralFlags.All) === NumericLiteralFlags.None - && !(expression).isOctalLiteral - && text.indexOf(tokenToString(SyntaxKind.DotToken)) < 0; - } - else if (isPropertyAccessExpression(expression) || isElementAccessExpression(expression)) { - // check if constant enum value is integer - const constantValue = getConstantValue(expression); - // isFinite handles cases when constantValue is undefined - return isFinite(constantValue) - && Math.floor(constantValue) === constantValue - && compilerOptions.removeComments; - } - } - - function emitElementAccessExpression(node: ElementAccessExpression) { - emitExpression(node.expression); - write("["); - emitExpression(node.argumentExpression); - write("]"); - } - - function emitCallExpression(node: CallExpression) { - emitExpression(node.expression); - emitTypeArguments(node, node.typeArguments); - emitExpressionList(node, node.arguments, ListFormat.CallExpressionArguments); - } - - function emitNewExpression(node: NewExpression) { - write("new "); - emitExpression(node.expression); - emitTypeArguments(node, node.typeArguments); - emitExpressionList(node, node.arguments, ListFormat.NewExpressionArguments); - } - - function emitTaggedTemplateExpression(node: TaggedTemplateExpression) { - emitExpression(node.tag); - write(" "); - emitExpression(node.template); - } - - function emitTypeAssertionExpression(node: TypeAssertion) { - write("<"); - emit(node.type); - write(">"); - emitExpression(node.expression); - } - - function emitParenthesizedExpression(node: ParenthesizedExpression) { - write("("); - emitExpression(node.expression); - write(")"); - } - - function emitFunctionExpression(node: FunctionExpression) { - emitFunctionDeclarationOrExpression(node); - } - - function emitArrowFunction(node: ArrowFunction) { - emitDecorators(node, node.decorators); - emitModifiers(node, node.modifiers); - emitSignatureAndBody(node, emitArrowFunctionHead); - } - - function emitArrowFunctionHead(node: ArrowFunction) { - emitTypeParameters(node, node.typeParameters); - emitParametersForArrow(node, node.parameters); - emitWithPrefix(": ", node.type); - write(" =>"); - } - - function emitDeleteExpression(node: DeleteExpression) { - write("delete "); - emitExpression(node.expression); - } - - function emitTypeOfExpression(node: TypeOfExpression) { - write("typeof "); - emitExpression(node.expression); - } - - function emitVoidExpression(node: VoidExpression) { - write("void "); - emitExpression(node.expression); - } - - function emitAwaitExpression(node: AwaitExpression) { - write("await "); - emitExpression(node.expression); - } - - function emitPrefixUnaryExpression(node: PrefixUnaryExpression) { - writeTokenText(node.operator); - if (shouldEmitWhitespaceBeforeOperand(node)) { - write(" "); - } - emitExpression(node.operand); - } - - function shouldEmitWhitespaceBeforeOperand(node: PrefixUnaryExpression) { - // In some cases, we need to emit a space between the operator and the operand. One obvious case - // is when the operator is an identifier, like delete or typeof. We also need to do this for plus - // and minus expressions in certain cases. Specifically, consider the following two cases (parens - // are just for clarity of exposition, and not part of the source code): - // - // (+(+1)) - // (+(++1)) - // - // We need to emit a space in both cases. In the first case, the absence of a space will make - // the resulting expression a prefix increment operation. And in the second, it will make the resulting - // expression a prefix increment whose operand is a plus expression - (++(+x)) - // The same is true of minus of course. - const operand = node.operand; - return operand.kind === SyntaxKind.PrefixUnaryExpression - && ((node.operator === SyntaxKind.PlusToken && ((operand).operator === SyntaxKind.PlusToken || (operand).operator === SyntaxKind.PlusPlusToken)) - || (node.operator === SyntaxKind.MinusToken && ((operand).operator === SyntaxKind.MinusToken || (operand).operator === SyntaxKind.MinusMinusToken))); - } - - function emitPostfixUnaryExpression(node: PostfixUnaryExpression) { - emitExpression(node.operand); - writeTokenText(node.operator); - } - - function emitBinaryExpression(node: BinaryExpression) { - const isCommaOperator = node.operatorToken.kind !== SyntaxKind.CommaToken; - const indentBeforeOperator = needsIndentation(node, node.left, node.operatorToken); - const indentAfterOperator = needsIndentation(node, node.operatorToken, node.right); - - emitExpression(node.left); - increaseIndentIf(indentBeforeOperator, isCommaOperator ? " " : undefined); - writeTokenText(node.operatorToken.kind); - increaseIndentIf(indentAfterOperator, " "); - emitExpression(node.right); - decreaseIndentIf(indentBeforeOperator, indentAfterOperator); - } - - function emitConditionalExpression(node: ConditionalExpression) { - const indentBeforeQuestion = needsIndentation(node, node.condition, node.questionToken); - const indentAfterQuestion = needsIndentation(node, node.questionToken, node.whenTrue); - const indentBeforeColon = needsIndentation(node, node.whenTrue, node.colonToken); - const indentAfterColon = needsIndentation(node, node.colonToken, node.whenFalse); - - emitExpression(node.condition); - increaseIndentIf(indentBeforeQuestion, " "); - write("?"); - increaseIndentIf(indentAfterQuestion, " "); - emitExpression(node.whenTrue); - decreaseIndentIf(indentBeforeQuestion, indentAfterQuestion); - - increaseIndentIf(indentBeforeColon, " "); - write(":"); - increaseIndentIf(indentAfterColon, " "); - emitExpression(node.whenFalse); - decreaseIndentIf(indentBeforeColon, indentAfterColon); - } - - function emitTemplateExpression(node: TemplateExpression) { - emit(node.head); - emitList(node, node.templateSpans, ListFormat.TemplateExpressionSpans); - } - - function emitYieldExpression(node: YieldExpression) { - write(node.asteriskToken ? "yield*" : "yield"); - emitExpressionWithPrefix(" ", node.expression); - } - - function emitSpreadExpression(node: SpreadElement) { - write("..."); - emitExpression(node.expression); - } - - function emitClassExpression(node: ClassExpression) { - emitClassDeclarationOrExpression(node); - } - - function emitExpressionWithTypeArguments(node: ExpressionWithTypeArguments) { - emitExpression(node.expression); - emitTypeArguments(node, node.typeArguments); - } - - function emitAsExpression(node: AsExpression) { - emitExpression(node.expression); - if (node.type) { - write(" as "); - emit(node.type); - } - } - - function emitNonNullExpression(node: NonNullExpression) { - emitExpression(node.expression); - write("!"); - } - - function emitMetaProperty(node: MetaProperty) { - writeToken(node.keywordToken, node.pos); - write("."); - emit(node.name); - } - - // - // Misc - // - - function emitTemplateSpan(node: TemplateSpan) { - emitExpression(node.expression); - emit(node.literal); - } - - // - // Statements - // - - function emitBlock(node: Block) { - if (isSingleLineEmptyBlock(node)) { - writeToken(SyntaxKind.OpenBraceToken, node.pos, /*contextNode*/ node); - write(" "); - writeToken(SyntaxKind.CloseBraceToken, node.statements.end, /*contextNode*/ node); - } - else { - writeToken(SyntaxKind.OpenBraceToken, node.pos, /*contextNode*/ node); - emitBlockStatements(node); - writeToken(SyntaxKind.CloseBraceToken, node.statements.end, /*contextNode*/ node); - } - } - - function emitBlockStatements(node: BlockLike) { - if (getEmitFlags(node) & EmitFlags.SingleLine) { - emitList(node, node.statements, ListFormat.SingleLineBlockStatements); - } - else { - emitList(node, node.statements, ListFormat.MultiLineBlockStatements); - } - } - - function emitVariableStatement(node: VariableStatement) { - emitModifiers(node, node.modifiers); - emit(node.declarationList); - write(";"); - } - - function emitEmptyStatement() { - write(";"); - } - - function emitExpressionStatement(node: ExpressionStatement) { - emitExpression(node.expression); - write(";"); - } - - function emitIfStatement(node: IfStatement) { - const openParenPos = writeToken(SyntaxKind.IfKeyword, node.pos, node); - write(" "); - writeToken(SyntaxKind.OpenParenToken, openParenPos, node); - emitExpression(node.expression); - writeToken(SyntaxKind.CloseParenToken, node.expression.end, node); - emitEmbeddedStatement(node, node.thenStatement); - if (node.elseStatement) { - writeLineOrSpace(node); - writeToken(SyntaxKind.ElseKeyword, node.thenStatement.end, node); - if (node.elseStatement.kind === SyntaxKind.IfStatement) { - write(" "); - emit(node.elseStatement); - } - else { - emitEmbeddedStatement(node, node.elseStatement); - } - } - } - - function emitDoStatement(node: DoStatement) { - write("do"); - emitEmbeddedStatement(node, node.statement); - if (isBlock(node.statement)) { - write(" "); - } - else { - writeLineOrSpace(node); - } - - write("while ("); - emitExpression(node.expression); - write(");"); - } - - function emitWhileStatement(node: WhileStatement) { - write("while ("); - emitExpression(node.expression); - write(")"); - emitEmbeddedStatement(node, node.statement); - } - - function emitForStatement(node: ForStatement) { - const openParenPos = writeToken(SyntaxKind.ForKeyword, node.pos); - write(" "); - writeToken(SyntaxKind.OpenParenToken, openParenPos, /*contextNode*/ node); - emitForBinding(node.initializer); - write(";"); - emitExpressionWithPrefix(" ", node.condition); - write(";"); - emitExpressionWithPrefix(" ", node.incrementor); - write(")"); - emitEmbeddedStatement(node, node.statement); - } - - function emitForInStatement(node: ForInStatement) { - const openParenPos = writeToken(SyntaxKind.ForKeyword, node.pos); - write(" "); - writeToken(SyntaxKind.OpenParenToken, openParenPos); - emitForBinding(node.initializer); - write(" in "); - emitExpression(node.expression); - writeToken(SyntaxKind.CloseParenToken, node.expression.end); - emitEmbeddedStatement(node, node.statement); - } - - function emitForOfStatement(node: ForOfStatement) { - const openParenPos = writeToken(SyntaxKind.ForKeyword, node.pos); - write(" "); - writeToken(SyntaxKind.OpenParenToken, openParenPos); - emitForBinding(node.initializer); - write(" of "); - emitExpression(node.expression); - writeToken(SyntaxKind.CloseParenToken, node.expression.end); - emitEmbeddedStatement(node, node.statement); - } - - function emitForBinding(node: VariableDeclarationList | Expression) { - if (node !== undefined) { - if (node.kind === SyntaxKind.VariableDeclarationList) { - emit(node); - } - else { - emitExpression(node); - } - } - } - - function emitContinueStatement(node: ContinueStatement) { - writeToken(SyntaxKind.ContinueKeyword, node.pos); - emitWithPrefix(" ", node.label); - write(";"); - } - - function emitBreakStatement(node: BreakStatement) { - writeToken(SyntaxKind.BreakKeyword, node.pos); - emitWithPrefix(" ", node.label); - write(";"); - } - - function emitReturnStatement(node: ReturnStatement) { - writeToken(SyntaxKind.ReturnKeyword, node.pos, /*contextNode*/ node); - emitExpressionWithPrefix(" ", node.expression); - write(";"); - } - - function emitWithStatement(node: WithStatement) { - write("with ("); - emitExpression(node.expression); - write(")"); - emitEmbeddedStatement(node, node.statement); - } - - function emitSwitchStatement(node: SwitchStatement) { - const openParenPos = writeToken(SyntaxKind.SwitchKeyword, node.pos); - write(" "); - writeToken(SyntaxKind.OpenParenToken, openParenPos); - emitExpression(node.expression); - writeToken(SyntaxKind.CloseParenToken, node.expression.end); - write(" "); - emit(node.caseBlock); - } - - function emitLabeledStatement(node: LabeledStatement) { - emit(node.label); - write(": "); - emit(node.statement); - } - - function emitThrowStatement(node: ThrowStatement) { - write("throw"); - emitExpressionWithPrefix(" ", node.expression); - write(";"); - } - - function emitTryStatement(node: TryStatement) { - write("try "); - emit(node.tryBlock); - if (node.catchClause) { - writeLineOrSpace(node); - emit(node.catchClause); - } - if (node.finallyBlock) { - writeLineOrSpace(node); - write("finally "); - emit(node.finallyBlock); - } - } - - function emitDebuggerStatement(node: DebuggerStatement) { - writeToken(SyntaxKind.DebuggerKeyword, node.pos); - write(";"); - } - - // - // Declarations - // - - function emitVariableDeclaration(node: VariableDeclaration) { - emit(node.name); - emitWithPrefix(": ", node.type); - emitExpressionWithPrefix(" = ", node.initializer); - } - - function emitVariableDeclarationList(node: VariableDeclarationList) { - write(isLet(node) ? "let " : isConst(node) ? "const " : "var "); - emitList(node, node.declarations, ListFormat.VariableDeclarationList); - } - - function emitFunctionDeclaration(node: FunctionDeclaration) { - emitFunctionDeclarationOrExpression(node); - } - - function emitFunctionDeclarationOrExpression(node: FunctionDeclaration | FunctionExpression) { - emitDecorators(node, node.decorators); - emitModifiers(node, node.modifiers); - write(node.asteriskToken ? "function* " : "function "); - emitIdentifierName(node.name); - emitSignatureAndBody(node, emitSignatureHead); - } - - function emitSignatureAndBody(node: FunctionLikeDeclaration, emitSignatureHead: (node: SignatureDeclaration) => void) { - const body = node.body; - if (body) { - if (isBlock(body)) { - const indentedFlag = getEmitFlags(node) & EmitFlags.Indented; - if (indentedFlag) { - increaseIndent(); - } - - if (getEmitFlags(node) & EmitFlags.ReuseTempVariableScope) { - emitSignatureHead(node); - emitBlockFunctionBody(body); - } - else { - pushNameGenerationScope(); - emitSignatureHead(node); - emitBlockFunctionBody(body); - popNameGenerationScope(); - } - - if (indentedFlag) { - decreaseIndent(); - } - } - else { - emitSignatureHead(node); - write(" "); - emitExpression(body); - } - } - else { - emitSignatureHead(node); - write(";"); - } - - } - - function emitSignatureHead(node: FunctionDeclaration | FunctionExpression | MethodDeclaration | AccessorDeclaration | ConstructorDeclaration) { - emitTypeParameters(node, node.typeParameters); - emitParameters(node, node.parameters); - emitWithPrefix(": ", node.type); - } - - function shouldEmitBlockFunctionBodyOnSingleLine(body: Block) { - // We must emit a function body as a single-line body in the following case: - // * The body has NodeEmitFlags.SingleLine specified. - - // We must emit a function body as a multi-line body in the following cases: - // * The body is explicitly marked as multi-line. - // * A non-synthesized body's start and end position are on different lines. - // * Any statement in the body starts on a new line. - - if (getEmitFlags(body) & EmitFlags.SingleLine) { - return true; - } - - if (body.multiLine) { - return false; - } - - if (!nodeIsSynthesized(body) && !rangeIsOnSingleLine(body, currentSourceFile)) { - return false; - } - - if (shouldWriteLeadingLineTerminator(body, body.statements, ListFormat.PreserveLines) - || shouldWriteClosingLineTerminator(body, body.statements, ListFormat.PreserveLines)) { - return false; - } - - let previousStatement: Statement; - for (const statement of body.statements) { - if (shouldWriteSeparatingLineTerminator(previousStatement, statement, ListFormat.PreserveLines)) { - return false; - } - - previousStatement = statement; - } - - return true; - } - - function emitBlockFunctionBody(body: Block) { - write(" {"); - increaseIndent(); - - const emitBlockFunctionBody = shouldEmitBlockFunctionBodyOnSingleLine(body) - ? emitBlockFunctionBodyOnSingleLine - : emitBlockFunctionBodyWorker; - - emitBodyIndirect(body, body.statements, emitBlockFunctionBody); - - decreaseIndent(); - writeToken(SyntaxKind.CloseBraceToken, body.statements.end, body); - } - - function emitBlockFunctionBodyOnSingleLine(body: Block) { - emitBlockFunctionBodyWorker(body, /*emitBlockFunctionBodyOnSingleLine*/ true); - } - - function emitBlockFunctionBodyWorker(body: Block, emitBlockFunctionBodyOnSingleLine?: boolean) { - // Emit all the prologue directives (like "use strict"). - const statementOffset = emitPrologueDirectives(body.statements, /*startWithNewLine*/ true); - const pos = writer.getTextPos(); - emitHelpersIndirect(body); - if (statementOffset === 0 && pos === writer.getTextPos() && emitBlockFunctionBodyOnSingleLine) { - decreaseIndent(); - emitList(body, body.statements, ListFormat.SingleLineFunctionBodyStatements); - increaseIndent(); - } - else { - emitList(body, body.statements, ListFormat.MultiLineFunctionBodyStatements, statementOffset); - } - } - - function emitClassDeclaration(node: ClassDeclaration) { - emitClassDeclarationOrExpression(node); - } - - function emitClassDeclarationOrExpression(node: ClassDeclaration | ClassExpression) { - emitDecorators(node, node.decorators); - emitModifiers(node, node.modifiers); - write("class"); - emitNodeWithPrefix(" ", node.name, emitIdentifierName); - - const indentedFlag = getEmitFlags(node) & EmitFlags.Indented; - if (indentedFlag) { - increaseIndent(); - } - - emitTypeParameters(node, node.typeParameters); - emitList(node, node.heritageClauses, ListFormat.ClassHeritageClauses); - - pushNameGenerationScope(); - write(" {"); - emitList(node, node.members, ListFormat.ClassMembers); - write("}"); - popNameGenerationScope(); - - if (indentedFlag) { - decreaseIndent(); - } - } - - function emitInterfaceDeclaration(node: InterfaceDeclaration) { - emitDecorators(node, node.decorators); - emitModifiers(node, node.modifiers); - write("interface "); - emit(node.name); - emitTypeParameters(node, node.typeParameters); - emitList(node, node.heritageClauses, ListFormat.HeritageClauses); - write(" {"); - emitList(node, node.members, ListFormat.InterfaceMembers); - write("}"); - } - - function emitTypeAliasDeclaration(node: TypeAliasDeclaration) { - emitDecorators(node, node.decorators); - emitModifiers(node, node.modifiers); - write("type "); - emit(node.name); - emitTypeParameters(node, node.typeParameters); - write(" = "); - emit(node.type); - write(";"); - } - - function emitEnumDeclaration(node: EnumDeclaration) { - emitModifiers(node, node.modifiers); - write("enum "); - emit(node.name); - pushNameGenerationScope(); - write(" {"); - emitList(node, node.members, ListFormat.EnumMembers); - write("}"); - popNameGenerationScope(); - } - - function emitModuleDeclaration(node: ModuleDeclaration) { - emitModifiers(node, node.modifiers); - write(node.flags & NodeFlags.Namespace ? "namespace " : "module "); - emit(node.name); - - let body = node.body; - while (body.kind === SyntaxKind.ModuleDeclaration) { - write("."); - emit((body).name); - body = (body).body; - } - - write(" "); - emit(body); - } - - function emitModuleBlock(node: ModuleBlock) { - if (isEmptyBlock(node)) { - write("{ }"); - } - else { - pushNameGenerationScope(); - write("{"); - increaseIndent(); - emitBlockStatements(node); - write("}"); - popNameGenerationScope(); - } - } - - function emitCaseBlock(node: CaseBlock) { - writeToken(SyntaxKind.OpenBraceToken, node.pos); - emitList(node, node.clauses, ListFormat.CaseBlockClauses); - writeToken(SyntaxKind.CloseBraceToken, node.clauses.end); - } - - function emitImportEqualsDeclaration(node: ImportEqualsDeclaration) { - emitModifiers(node, node.modifiers); - write("import "); - emit(node.name); - write(" = "); - emitModuleReference(node.moduleReference); - write(";"); - } - - function emitModuleReference(node: ModuleReference) { - if (node.kind === SyntaxKind.Identifier) { - emitExpression(node); - } - else { - emit(node); - } - } - - function emitImportDeclaration(node: ImportDeclaration) { - emitModifiers(node, node.modifiers); - write("import "); - if (node.importClause) { - emit(node.importClause); - write(" from "); - } - emitExpression(node.moduleSpecifier); - write(";"); - } - - function emitImportClause(node: ImportClause) { - emit(node.name); - if (node.name && node.namedBindings) { - write(", "); - } - emit(node.namedBindings); - } - - function emitNamespaceImport(node: NamespaceImport) { - write("* as "); - emit(node.name); - } - - function emitNamedImports(node: NamedImports) { - emitNamedImportsOrExports(node); - } - - function emitImportSpecifier(node: ImportSpecifier) { - emitImportOrExportSpecifier(node); - } - - function emitExportAssignment(node: ExportAssignment) { - write(node.isExportEquals ? "export = " : "export default "); - emitExpression(node.expression); - write(";"); - } - - function emitExportDeclaration(node: ExportDeclaration) { - write("export "); - if (node.exportClause) { - emit(node.exportClause); - } - else { - write("*"); - } - if (node.moduleSpecifier) { - write(" from "); - emitExpression(node.moduleSpecifier); - } - write(";"); - } - - function emitNamedExports(node: NamedExports) { - emitNamedImportsOrExports(node); - } - - function emitExportSpecifier(node: ExportSpecifier) { - emitImportOrExportSpecifier(node); - } - - function emitNamedImportsOrExports(node: NamedImportsOrExports) { - write("{"); - emitList(node, node.elements, ListFormat.NamedImportsOrExportsElements); - write("}"); - } - - function emitImportOrExportSpecifier(node: ImportOrExportSpecifier) { - if (node.propertyName) { - emit(node.propertyName); - write(" as "); - } - - emit(node.name); - } - - // - // Module references - // - - function emitExternalModuleReference(node: ExternalModuleReference) { - write("require("); - emitExpression(node.expression); - write(")"); - } - - // - // JSX - // - - function emitJsxElement(node: JsxElement) { - emit(node.openingElement); - emitList(node, node.children, ListFormat.JsxElementChildren); - emit(node.closingElement); - } - - function emitJsxSelfClosingElement(node: JsxSelfClosingElement) { - write("<"); - emitJsxTagName(node.tagName); - write(" "); - emitList(node, node.attributes, ListFormat.JsxElementAttributes); - write("/>"); - } - - function emitJsxOpeningElement(node: JsxOpeningElement) { - write("<"); - emitJsxTagName(node.tagName); - writeIfAny(node.attributes, " "); - emitList(node, node.attributes, ListFormat.JsxElementAttributes); - write(">"); - } - - function emitJsxText(node: JsxText) { - writer.writeLiteral(getTextOfNode(node, /*includeTrivia*/ true)); - } - - function emitJsxClosingElement(node: JsxClosingElement) { - write(""); - } - - function emitJsxAttribute(node: JsxAttribute) { - emit(node.name); - emitWithPrefix("=", node.initializer); - } - - function emitJsxSpreadAttribute(node: JsxSpreadAttribute) { - write("{..."); - emitExpression(node.expression); - write("}"); - } - - function emitJsxExpression(node: JsxExpression) { - if (node.expression) { - write("{"); - if (node.dotDotDotToken) { - write("..."); - } - emitExpression(node.expression); - write("}"); - } - } - - function emitJsxTagName(node: JsxTagNameExpression) { - if (node.kind === SyntaxKind.Identifier) { - emitExpression(node); - } - else { - emit(node); - } - } - - // - // Clauses - // - - function emitCaseClause(node: CaseClause) { - write("case "); - emitExpression(node.expression); - write(":"); - - emitCaseOrDefaultClauseStatements(node, node.statements); - } - - function emitDefaultClause(node: DefaultClause) { - write("default:"); - emitCaseOrDefaultClauseStatements(node, node.statements); - } - - function emitCaseOrDefaultClauseStatements(parentNode: Node, statements: NodeArray) { - const emitAsSingleStatement = - statements.length === 1 && - ( - // treat synthesized nodes as located on the same line for emit purposes - nodeIsSynthesized(parentNode) || - nodeIsSynthesized(statements[0]) || - rangeStartPositionsAreOnSameLine(parentNode, statements[0], currentSourceFile) - ); - - if (emitAsSingleStatement) { - write(" "); - emit(statements[0]); - } - else { - emitList(parentNode, statements, ListFormat.CaseOrDefaultClauseStatements); - } - } - - function emitHeritageClause(node: HeritageClause) { - write(" "); - writeTokenText(node.token); - write(" "); - emitList(node, node.types, ListFormat.HeritageClauseTypes); - } - - function emitCatchClause(node: CatchClause) { - writeLine(); - const openParenPos = writeToken(SyntaxKind.CatchKeyword, node.pos); - write(" "); - writeToken(SyntaxKind.OpenParenToken, openParenPos); - emit(node.variableDeclaration); - writeToken(SyntaxKind.CloseParenToken, node.variableDeclaration ? node.variableDeclaration.end : openParenPos); - write(" "); - emit(node.block); - } - - // - // Property assignments - // - - function emitPropertyAssignment(node: PropertyAssignment) { - emit(node.name); - write(": "); - // This is to ensure that we emit comment in the following case: - // For example: - // obj = { - // id: /*comment1*/ ()=>void - // } - // "comment1" is not considered to be leading comment for node.initializer - // but rather a trailing comment on the previous node. - const initializer = node.initializer; - if (onEmitTrailingCommentsOfPosition && (getEmitFlags(initializer) & EmitFlags.NoLeadingComments) === 0) { - const commentRange = getCommentRange(initializer); - onEmitTrailingCommentsOfPosition(commentRange.pos); - } - emitExpression(initializer); - } - - function emitShorthandPropertyAssignment(node: ShorthandPropertyAssignment) { - emit(node.name); - if (node.objectAssignmentInitializer) { - write(" = "); - emitExpression(node.objectAssignmentInitializer); - } - } - - function emitSpreadAssignment(node: SpreadAssignment) { - if (node.expression) { - write("..."); - emitExpression(node.expression); - } - } - - // - // Enum - // - - function emitEnumMember(node: EnumMember) { - emit(node.name); - emitExpressionWithPrefix(" = ", node.initializer); - } - - // - // Top-level nodes - // - - function emitSourceFile(node: SourceFile) { - writeLine(); - emitShebang(); - emitBodyIndirect(node, node.statements, emitSourceFileWorker); - } - - function emitSourceFileWorker(node: SourceFile) { - const statements = node.statements; - const statementOffset = emitPrologueDirectives(statements); - pushNameGenerationScope(); - emitHelpersIndirect(node); - emitList(node, statements, ListFormat.MultiLine, statementOffset); - popNameGenerationScope(); - } - - // Transformation nodes - - function emitPartiallyEmittedExpression(node: PartiallyEmittedExpression) { - emitExpression(node.expression); - } - - /** - * Emits any prologue directives at the start of a Statement list, returning the - * number of prologue directives written to the output. - */ - function emitPrologueDirectives(statements: Node[], startWithNewLine?: boolean): number { - for (let i = 0; i < statements.length; i++) { - if (isPrologueDirective(statements[i])) { - if (startWithNewLine || i > 0) { - writeLine(); - } - emit(statements[i]); - } - else { - // return index of the first non prologue directive - return i; - } - } - - return statements.length; - } - - // - // Helpers - // - - function emitShebang() { - const shebang = getShebang(currentSourceFile.text); - if (shebang) { - write(shebang); - writeLine(); - } - } - - function emitModifiers(node: Node, modifiers: NodeArray) { - if (modifiers && modifiers.length) { - emitList(node, modifiers, ListFormat.Modifiers); - write(" "); - } - } - - function emitWithPrefix(prefix: string, node: Node) { - emitNodeWithPrefix(prefix, node, emit); - } - - function emitExpressionWithPrefix(prefix: string, node: Node) { - emitNodeWithPrefix(prefix, node, emitExpression); - } - - function emitNodeWithPrefix(prefix: string, node: Node, emit: (node: Node) => void) { - if (node) { - write(prefix); - emit(node); - } - } - - function emitWithSuffix(node: Node, suffix: string) { - if (node) { - emit(node); - write(suffix); - } - } - - function emitEmbeddedStatement(parent: Node, node: Statement) { - if (isBlock(node) || getEmitFlags(parent) & EmitFlags.SingleLine) { - write(" "); - emit(node); - } - else { - writeLine(); - increaseIndent(); - emit(node); - decreaseIndent(); - } - } - - function emitDecorators(parentNode: Node, decorators: NodeArray) { - emitList(parentNode, decorators, ListFormat.Decorators); - } - - function emitTypeArguments(parentNode: Node, typeArguments: NodeArray) { - emitList(parentNode, typeArguments, ListFormat.TypeArguments); - } - - function emitTypeParameters(parentNode: Node, typeParameters: NodeArray) { - emitList(parentNode, typeParameters, ListFormat.TypeParameters); - } - - function emitParameters(parentNode: Node, parameters: NodeArray) { - emitList(parentNode, parameters, ListFormat.Parameters); - } - - function emitParametersForArrow(parentNode: Node, parameters: NodeArray) { - if (parameters && - parameters.length === 1 && - parameters[0].type === undefined && - parameters[0].pos === parentNode.pos) { - emit(parameters[0]); - } - else { - emitParameters(parentNode, parameters); - } - } - - function emitParametersForIndexSignature(parentNode: Node, parameters: NodeArray) { - emitList(parentNode, parameters, ListFormat.IndexSignatureParameters); - } - - function emitList(parentNode: Node, children: NodeArray, format: ListFormat, start?: number, count?: number) { - emitNodeList(emit, parentNode, children, format, start, count); - } - - function emitExpressionList(parentNode: Node, children: NodeArray, format: ListFormat, start?: number, count?: number) { - emitNodeList(emitExpression, parentNode, children, format, start, count); - } - - function emitNodeList(emit: (node: Node) => void, parentNode: Node, children: NodeArray, format: ListFormat, start = 0, count = children ? children.length - start : 0) { - const isUndefined = children === undefined; - if (isUndefined && format & ListFormat.OptionalIfUndefined) { - return; - } - - const isEmpty = isUndefined || children.length === 0 || start >= children.length || count === 0; - if (isEmpty && format & ListFormat.OptionalIfEmpty) { - return; - } - - if (format & ListFormat.BracketsMask) { - write(getOpeningBracket(format)); - } - - if (isEmpty) { - // Write a line terminator if the parent node was multi-line - if (format & ListFormat.MultiLine) { - writeLine(); - } - else if (format & ListFormat.SpaceBetweenBraces) { - write(" "); - } - } - else { - // Write the opening line terminator or leading whitespace. - const mayEmitInterveningComments = (format & ListFormat.NoInterveningComments) === 0; - let shouldEmitInterveningComments = mayEmitInterveningComments; - if (shouldWriteLeadingLineTerminator(parentNode, children, format)) { - writeLine(); - shouldEmitInterveningComments = false; - } - else if (format & ListFormat.SpaceBetweenBraces) { - write(" "); - } - - // Increase the indent, if requested. - if (format & ListFormat.Indented) { - increaseIndent(); - } - - // Emit each child. - let previousSibling: Node; - let shouldDecreaseIndentAfterEmit: boolean; - const delimiter = getDelimiter(format); - for (let i = 0; i < count; i++) { - const child = children[start + i]; - - // Write the delimiter if this is not the first node. - if (previousSibling) { - write(delimiter); - - // Write either a line terminator or whitespace to separate the elements. - if (shouldWriteSeparatingLineTerminator(previousSibling, child, format)) { - // If a synthesized node in a single-line list starts on a new - // line, we should increase the indent. - if ((format & (ListFormat.LinesMask | ListFormat.Indented)) === ListFormat.SingleLine) { - increaseIndent(); - shouldDecreaseIndentAfterEmit = true; - } - - writeLine(); - shouldEmitInterveningComments = false; - } - else if (previousSibling && format & ListFormat.SpaceBetweenSiblings) { - write(" "); - } - } - - // Emit this child. - if (shouldEmitInterveningComments) { - if (onEmitTrailingCommentsOfPosition) { - const commentRange = getCommentRange(child); - onEmitTrailingCommentsOfPosition(commentRange.pos); - } - } - else { - shouldEmitInterveningComments = mayEmitInterveningComments; - } - - emit(child); - - if (shouldDecreaseIndentAfterEmit) { - decreaseIndent(); - shouldDecreaseIndentAfterEmit = false; - } - - previousSibling = child; - } - - // Write a trailing comma, if requested. - const hasTrailingComma = (format & ListFormat.AllowTrailingComma) && children.hasTrailingComma; - if (format & ListFormat.CommaDelimited && hasTrailingComma) { - write(","); - } - - // Decrease the indent, if requested. - if (format & ListFormat.Indented) { - decreaseIndent(); - } - - // Write the closing line terminator or closing whitespace. - if (shouldWriteClosingLineTerminator(parentNode, children, format)) { - writeLine(); - } - else if (format & ListFormat.SpaceBetweenBraces) { - write(" "); - } - } - - if (format & ListFormat.BracketsMask) { - write(getClosingBracket(format)); - } - } - - function writeIfAny(nodes: NodeArray, text: string) { - if (some(nodes)) { - write(text); - } - } - - function writeIfPresent(node: Node, text: string) { - if (node) { - write(text); - } - } - - function writeToken(token: SyntaxKind, pos: number, contextNode?: Node) { - return onEmitSourceMapOfToken - ? onEmitSourceMapOfToken(contextNode, token, pos, writeTokenText) - : writeTokenText(token, pos); - } - - function writeTokenText(token: SyntaxKind, pos?: number) { - const tokenString = tokenToString(token); - write(tokenString); - return pos < 0 ? pos : pos + tokenString.length; - } - - function writeLineOrSpace(node: Node) { - if (getEmitFlags(node) & EmitFlags.SingleLine) { - write(" "); - } - else { - writeLine(); - } - } - - function writeLines(text: string): void { - const lines = text.split(/\r\n?|\n/g); - const indentation = guessIndentation(lines); - for (let i = 0; i < lines.length; i++) { - const line = indentation ? lines[i].slice(indentation) : lines[i]; - if (line.length) { - writeLine(); - write(line); - writeLine(); - } - } - } - - function guessIndentation(lines: string[]) { - let indentation: number; - for (const line of lines) { - for (let i = 0; i < line.length && (indentation === undefined || i < indentation); i++) { - if (!isWhiteSpace(line.charCodeAt(i))) { - if (indentation === undefined || i < indentation) { - indentation = i; - break; - } - } - } - } - return indentation; - } - - function increaseIndentIf(value: boolean, valueToWriteWhenNotIndenting?: string) { - if (value) { - increaseIndent(); - writeLine(); - } - else if (valueToWriteWhenNotIndenting) { - write(valueToWriteWhenNotIndenting); - } - } - - // Helper function to decrease the indent if we previously indented. Allows multiple - // previous indent values to be considered at a time. This also allows caller to just - // call this once, passing in all their appropriate indent values, instead of needing - // to call this helper function multiple times. - function decreaseIndentIf(value1: boolean, value2?: boolean) { - if (value1) { - decreaseIndent(); - } - if (value2) { - decreaseIndent(); - } - } - - function shouldWriteLeadingLineTerminator(parentNode: Node, children: NodeArray, format: ListFormat) { - if (format & ListFormat.MultiLine) { - return true; - } - - if (format & ListFormat.PreserveLines) { - if (format & ListFormat.PreferNewLine) { - return true; - } - - const firstChild = children[0]; - if (firstChild === undefined) { - return !rangeIsOnSingleLine(parentNode, currentSourceFile); - } - else if (positionIsSynthesized(parentNode.pos) || nodeIsSynthesized(firstChild)) { - return synthesizedNodeStartsOnNewLine(firstChild, format); - } - else { - return !rangeStartPositionsAreOnSameLine(parentNode, firstChild, currentSourceFile); - } - } - else { - return false; - } - } - - function shouldWriteSeparatingLineTerminator(previousNode: Node, nextNode: Node, format: ListFormat) { - if (format & ListFormat.MultiLine) { - return true; - } - else if (format & ListFormat.PreserveLines) { - if (previousNode === undefined || nextNode === undefined) { - return false; - } - else if (nodeIsSynthesized(previousNode) || nodeIsSynthesized(nextNode)) { - return synthesizedNodeStartsOnNewLine(previousNode, format) || synthesizedNodeStartsOnNewLine(nextNode, format); - } - else { - return !rangeEndIsOnSameLineAsRangeStart(previousNode, nextNode, currentSourceFile); - } - } - else { - return nextNode.startsOnNewLine; - } - } - - function shouldWriteClosingLineTerminator(parentNode: Node, children: NodeArray, format: ListFormat) { - if (format & ListFormat.MultiLine) { - return (format & ListFormat.NoTrailingNewLine) === 0; - } - else if (format & ListFormat.PreserveLines) { - if (format & ListFormat.PreferNewLine) { - return true; - } - - const lastChild = lastOrUndefined(children); - if (lastChild === undefined) { - return !rangeIsOnSingleLine(parentNode, currentSourceFile); - } - else if (positionIsSynthesized(parentNode.pos) || nodeIsSynthesized(lastChild)) { - return synthesizedNodeStartsOnNewLine(lastChild, format); - } - else { - return !rangeEndPositionsAreOnSameLine(parentNode, lastChild, currentSourceFile); - } - } - else { - return false; - } - } - - function synthesizedNodeStartsOnNewLine(node: Node, format?: ListFormat) { - if (nodeIsSynthesized(node)) { - const startsOnNewLine = node.startsOnNewLine; - if (startsOnNewLine === undefined) { - return (format & ListFormat.PreferNewLine) !== 0; - } - - return startsOnNewLine; - } - - return (format & ListFormat.PreferNewLine) !== 0; - } - - function needsIndentation(parent: Node, node1: Node, node2: Node): boolean { - parent = skipSynthesizedParentheses(parent); - node1 = skipSynthesizedParentheses(node1); - node2 = skipSynthesizedParentheses(node2); - - // Always use a newline for synthesized code if the synthesizer desires it. - if (node2.startsOnNewLine) { - return true; - } - - return !nodeIsSynthesized(parent) - && !nodeIsSynthesized(node1) - && !nodeIsSynthesized(node2) - && !rangeEndIsOnSameLineAsRangeStart(node1, node2, currentSourceFile); - } - - function isSingleLineEmptyBlock(block: Block) { - return !block.multiLine - && isEmptyBlock(block); - } - - function isEmptyBlock(block: BlockLike) { - return block.statements.length === 0 - && rangeEndIsOnSameLineAsRangeStart(block, block, currentSourceFile); - } - - function skipSynthesizedParentheses(node: Node) { - while (node.kind === SyntaxKind.ParenthesizedExpression && nodeIsSynthesized(node)) { - node = (node).expression; - } - - return node; - } - - function getTextOfNode(node: Node, includeTrivia?: boolean): string { - if (isGeneratedIdentifier(node)) { - return generateName(node); - } - else if (isIdentifier(node) && (nodeIsSynthesized(node) || !node.parent)) { - return unescapeIdentifier(node.text); - } - else if (node.kind === SyntaxKind.StringLiteral && (node).textSourceNode) { - return getTextOfNode((node).textSourceNode, includeTrivia); - } - else if (isLiteralExpression(node) && (nodeIsSynthesized(node) || !node.parent)) { - return node.text; - } - - return getSourceTextOfNodeFromSourceFile(currentSourceFile, node, includeTrivia); - } - - function getLiteralTextOfNode(node: LiteralLikeNode): string { - if (node.kind === SyntaxKind.StringLiteral && (node).textSourceNode) { - const textSourceNode = (node).textSourceNode; - if (isIdentifier(textSourceNode)) { - return "\"" + escapeNonAsciiCharacters(escapeString(getTextOfNode(textSourceNode))) + "\""; - } - else { - return getLiteralTextOfNode(textSourceNode); - } - } - - return getLiteralText(node, currentSourceFile, languageVersion); - } - - function resetGeneratedNames() { - nodeIdToGeneratedName = undefined; - autoGeneratedIdToGeneratedName = undefined; - generatedNames = undefined; - tempFlagsStack = undefined; - tempFlags = TempFlags.Auto; - } - - function ensureNameGeneration() { - if (generatedNames === undefined) { - nodeIdToGeneratedName = []; - autoGeneratedIdToGeneratedName = []; - generatedNames = createMap(); - tempFlagsStack = []; - } - } - - /** - * Push a new name generation scope. - */ - function pushNameGenerationScope() { - ensureNameGeneration(); - tempFlagsStack.push(tempFlags); - tempFlags = 0; - } - - /** - * Pop the current name generation scope. - */ - function popNameGenerationScope() { - ensureNameGeneration(); - tempFlags = tempFlagsStack.pop(); - } - - /** - * Generate the text for a generated identifier. - */ - function generateName(name: GeneratedIdentifier) { - ensureNameGeneration(); - if (name.autoGenerateKind === GeneratedIdentifierKind.Node) { - // Node names generate unique names based on their original node - // and are cached based on that node's id. - const node = getNodeForGeneratedName(name); - return generateNameCached(node, getTextOfNode); - } - else { - // Auto, Loop, and Unique names are cached based on their unique - // autoGenerateId. - const autoGenerateId = name.autoGenerateId; - return autoGeneratedIdToGeneratedName[autoGenerateId] || (autoGeneratedIdToGeneratedName[autoGenerateId] = unescapeIdentifier(makeName(name))); - } - } - - function generateNameCached(node: Node, getTextOfNode: (node: Node, includeTrivia?: boolean) => string) { - const nodeId = getNodeId(node); - return nodeIdToGeneratedName[nodeId] || (nodeIdToGeneratedName[nodeId] = unescapeIdentifier(generateNameForNode(node, getTextOfNode))); - } - - /** - * Returns a value indicating whether a name is unique globally, within the current file, - * or within the NameGenerator. - */ - function isUniqueName(name: string): boolean { - return !(hasGlobalName && hasGlobalName(name)) - && !currentSourceFile.identifiers.has(name) - && !generatedNames.has(name); - } - - /** - * Returns a value indicating whether a name is unique within a container. - */ - function isUniqueLocalName(name: string, container: Node): boolean { - for (let node = container; isNodeDescendantOf(node, container); node = node.nextContainer) { - if (node.locals) { - const local = node.locals.get(name); - // We conservatively include alias symbols to cover cases where they're emitted as locals - if (local && local.flags & (SymbolFlags.Value | SymbolFlags.ExportValue | SymbolFlags.Alias)) { - return false; - } - } - } - return true; - } - - /** - * Return the next available name in the pattern _a ... _z, _0, _1, ... - * TempFlags._i or TempFlags._n may be used to express a preference for that dedicated name. - * Note that names generated by makeTempVariableName and makeUniqueName will never conflict. - */ - function makeTempVariableName(flags: TempFlags): string { - if (flags && !(tempFlags & flags)) { - const name = flags === TempFlags._i ? "_i" : "_n"; - if (isUniqueName(name)) { - tempFlags |= flags; - return name; - } - } - while (true) { - const count = tempFlags & TempFlags.CountMask; - tempFlags++; - // Skip over 'i' and 'n' - if (count !== 8 && count !== 13) { - const name = count < 26 - ? "_" + String.fromCharCode(CharacterCodes.a + count) - : "_" + (count - 26); - if (isUniqueName(name)) { - return name; - } - } - } - } - - /** - * Generate a name that is unique within the current file and doesn't conflict with any names - * in global scope. The name is formed by adding an '_n' suffix to the specified base name, - * where n is a positive integer. Note that names generated by makeTempVariableName and - * makeUniqueName are guaranteed to never conflict. - */ - function makeUniqueName(baseName: string): string { - // Find the first unique 'name_n', where n is a positive number - if (baseName.charCodeAt(baseName.length - 1) !== CharacterCodes._) { - baseName += "_"; - } - let i = 1; - while (true) { - const generatedName = baseName + i; - if (isUniqueName(generatedName)) { - generatedNames.set(generatedName, generatedName); - return generatedName; - } - i++; - } - } - - /** - * Generates a unique name for a ModuleDeclaration or EnumDeclaration. - */ - function generateNameForModuleOrEnum(node: ModuleDeclaration | EnumDeclaration, getTextOfNode: (node: Node, includeTrivia?: boolean) => string) { - const name = getTextOfNode(node.name); - // Use module/enum name itself if it is unique, otherwise make a unique variation - return isUniqueLocalName(name, node) ? name : makeUniqueName(name); - } - - /** - * Generates a unique name for an ImportDeclaration or ExportDeclaration. - */ - function generateNameForImportOrExportDeclaration(node: ImportDeclaration | ExportDeclaration) { - const expr = getExternalModuleName(node); - const baseName = expr.kind === SyntaxKind.StringLiteral ? - escapeIdentifier(makeIdentifierFromModuleName((expr).text)) : "module"; - return makeUniqueName(baseName); - } - - /** - * Generates a unique name for a default export. - */ - function generateNameForExportDefault() { - return makeUniqueName("default"); - } - - /** - * Generates a unique name for a class expression. - */ - function generateNameForClassExpression() { - return makeUniqueName("class"); - } - - function generateNameForMethodOrAccessor(node: MethodDeclaration | AccessorDeclaration, getTextOfNode: (node: Node, includeTrivia?: boolean) => string) { - if (isIdentifier(node.name)) { - return generateNameCached(node.name, getTextOfNode); - } - return makeTempVariableName(TempFlags.Auto); - } - - /** - * Generates a unique name from a node. - */ - function generateNameForNode(node: Node, getTextOfNode: (node: Node, includeTrivia?: boolean) => string): string { - switch (node.kind) { - case SyntaxKind.Identifier: - return makeUniqueName(getTextOfNode(node)); - case SyntaxKind.ModuleDeclaration: - case SyntaxKind.EnumDeclaration: - return generateNameForModuleOrEnum(node, getTextOfNode); - case SyntaxKind.ImportDeclaration: - case SyntaxKind.ExportDeclaration: - return generateNameForImportOrExportDeclaration(node); - case SyntaxKind.FunctionDeclaration: - case SyntaxKind.ClassDeclaration: - case SyntaxKind.ExportAssignment: - return generateNameForExportDefault(); - case SyntaxKind.ClassExpression: - return generateNameForClassExpression(); - case SyntaxKind.MethodDeclaration: - case SyntaxKind.GetAccessor: - case SyntaxKind.SetAccessor: - return generateNameForMethodOrAccessor(node, getTextOfNode); - default: - return makeTempVariableName(TempFlags.Auto); - } - } - - /** - * Generates a unique identifier for a node. - */ - function makeName(name: GeneratedIdentifier) { - switch (name.autoGenerateKind) { - case GeneratedIdentifierKind.Auto: - return makeTempVariableName(TempFlags.Auto); - case GeneratedIdentifierKind.Loop: - return makeTempVariableName(TempFlags._i); - case GeneratedIdentifierKind.Unique: - return makeUniqueName(name.text); - } - - Debug.fail("Unsupported GeneratedIdentifierKind."); - } - - /** - * Gets the node from which a name should be generated. - */ - function getNodeForGeneratedName(name: GeneratedIdentifier) { - const autoGenerateId = name.autoGenerateId; - let node = name as Node; - let original = node.original; - while (original) { - node = original; - - // if "node" is a different generated name (having a different - // "autoGenerateId"), use it and stop traversing. - if (isIdentifier(node) - && node.autoGenerateKind === GeneratedIdentifierKind.Node - && node.autoGenerateId !== autoGenerateId) { - break; - } - - original = node.original; - } - - // otherwise, return the original node for the source; - return node; - } - } - - function createDelimiterMap() { - const delimiters: string[] = []; - delimiters[ListFormat.None] = ""; - delimiters[ListFormat.CommaDelimited] = ","; - delimiters[ListFormat.BarDelimited] = " |"; - delimiters[ListFormat.AmpersandDelimited] = " &"; - return delimiters; - } - - function getDelimiter(format: ListFormat) { - return delimiters[format & ListFormat.DelimitersMask]; - } - - function createBracketsMap() { - const brackets: string[][] = []; - brackets[ListFormat.Braces] = ["{", "}"]; - brackets[ListFormat.Parenthesis] = ["(", ")"]; - brackets[ListFormat.AngleBrackets] = ["<", ">"]; - brackets[ListFormat.SquareBrackets] = ["[", "]"]; - return brackets; - } - - function getOpeningBracket(format: ListFormat) { - return brackets[format & ListFormat.BracketsMask][0]; - } - - function getClosingBracket(format: ListFormat) { - return brackets[format & ListFormat.BracketsMask][1]; - } - - const enum ListFormat { - None = 0, - - // Line separators - SingleLine = 0, // Prints the list on a single line (default). - MultiLine = 1 << 0, // Prints the list on multiple lines. - PreserveLines = 1 << 1, // Prints the list using line preservation if possible. - LinesMask = SingleLine | MultiLine | PreserveLines, - - // Delimiters - NotDelimited = 0, // There is no delimiter between list items (default). - BarDelimited = 1 << 2, // Each list item is space-and-bar (" |") delimited. - AmpersandDelimited = 1 << 3, // Each list item is space-and-ampersand (" &") delimited. - CommaDelimited = 1 << 4, // Each list item is comma (",") delimited. - DelimitersMask = BarDelimited | AmpersandDelimited | CommaDelimited, - - AllowTrailingComma = 1 << 5, // Write a trailing comma (",") if present. - - // Whitespace - Indented = 1 << 6, // The list should be indented. - SpaceBetweenBraces = 1 << 7, // Inserts a space after the opening brace and before the closing brace. - SpaceBetweenSiblings = 1 << 8, // Inserts a space between each sibling node. - - // Brackets/Braces - Braces = 1 << 9, // The list is surrounded by "{" and "}". - Parenthesis = 1 << 10, // The list is surrounded by "(" and ")". - AngleBrackets = 1 << 11, // The list is surrounded by "<" and ">". - SquareBrackets = 1 << 12, // The list is surrounded by "[" and "]". - BracketsMask = Braces | Parenthesis | AngleBrackets | SquareBrackets, - - OptionalIfUndefined = 1 << 13, // Do not emit brackets if the list is undefined. - OptionalIfEmpty = 1 << 14, // Do not emit brackets if the list is empty. - Optional = OptionalIfUndefined | OptionalIfEmpty, - - // Other - PreferNewLine = 1 << 15, // Prefer adding a LineTerminator between synthesized nodes. - NoTrailingNewLine = 1 << 16, // Do not emit a trailing NewLine for a MultiLine list. - NoInterveningComments = 1 << 17, // Do not emit comments between each node - - // Precomputed Formats - Modifiers = SingleLine | SpaceBetweenSiblings, - HeritageClauses = SingleLine | SpaceBetweenSiblings, - TypeLiteralMembers = MultiLine | Indented, - TupleTypeElements = CommaDelimited | SpaceBetweenSiblings | SingleLine | Indented, - UnionTypeConstituents = BarDelimited | SpaceBetweenSiblings | SingleLine, - IntersectionTypeConstituents = AmpersandDelimited | SpaceBetweenSiblings | SingleLine, - ObjectBindingPatternElements = SingleLine | AllowTrailingComma | SpaceBetweenBraces | CommaDelimited | SpaceBetweenSiblings, - ArrayBindingPatternElements = SingleLine | AllowTrailingComma | CommaDelimited | SpaceBetweenSiblings, - ObjectLiteralExpressionProperties = PreserveLines | CommaDelimited | SpaceBetweenSiblings | SpaceBetweenBraces | Indented | Braces, - ArrayLiteralExpressionElements = PreserveLines | CommaDelimited | SpaceBetweenSiblings | AllowTrailingComma | Indented | SquareBrackets, - CallExpressionArguments = CommaDelimited | SpaceBetweenSiblings | SingleLine | Parenthesis, - NewExpressionArguments = CommaDelimited | SpaceBetweenSiblings | SingleLine | Parenthesis | OptionalIfUndefined, - TemplateExpressionSpans = SingleLine | NoInterveningComments, - SingleLineBlockStatements = SpaceBetweenBraces | SpaceBetweenSiblings | SingleLine, - MultiLineBlockStatements = Indented | MultiLine, - VariableDeclarationList = CommaDelimited | SpaceBetweenSiblings | SingleLine, - SingleLineFunctionBodyStatements = SingleLine | SpaceBetweenSiblings | SpaceBetweenBraces, - MultiLineFunctionBodyStatements = MultiLine, - ClassHeritageClauses = SingleLine | SpaceBetweenSiblings, - ClassMembers = Indented | MultiLine, - InterfaceMembers = Indented | MultiLine, - EnumMembers = CommaDelimited | Indented | MultiLine, - CaseBlockClauses = Indented | MultiLine, - NamedImportsOrExportsElements = CommaDelimited | SpaceBetweenSiblings | AllowTrailingComma | SingleLine | SpaceBetweenBraces, - JsxElementChildren = SingleLine | NoInterveningComments, - JsxElementAttributes = SingleLine | SpaceBetweenSiblings | NoInterveningComments, - CaseOrDefaultClauseStatements = Indented | MultiLine | NoTrailingNewLine | OptionalIfEmpty, - HeritageClauseTypes = CommaDelimited | SpaceBetweenSiblings | SingleLine, - SourceFileStatements = MultiLine | NoTrailingNewLine, - Decorators = MultiLine | Optional, - TypeArguments = CommaDelimited | SpaceBetweenSiblings | SingleLine | Indented | AngleBrackets | Optional, - TypeParameters = CommaDelimited | SpaceBetweenSiblings | SingleLine | Indented | AngleBrackets | Optional, - Parameters = CommaDelimited | SpaceBetweenSiblings | SingleLine | Indented | Parenthesis, - IndexSignatureParameters = CommaDelimited | SpaceBetweenSiblings | SingleLine | Indented | SquareBrackets, - } -} \ No newline at end of file diff --git a/src/compiler/tsconfig.json b/src/compiler/tsconfig.json index 54d5eb77e10..52bb92ee1f0 100644 --- a/src/compiler/tsconfig.json +++ b/src/compiler/tsconfig.json @@ -34,7 +34,6 @@ "comments.ts", "sourcemap.ts", "declarationEmitter.ts", - "printer.ts", "emitter.ts", "program.ts", "commandLineParser.ts", diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 682cd9e617b..99cdca407b6 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -558,6 +558,15 @@ export type ModifiersArray = NodeArray; + /*@internal*/ + export const enum GeneratedIdentifierKind { + None, // Not automatically generated. + Auto, // Automatically generated identifier. + Loop, // Automatically generated identifier with a preference for '_i'. + Unique, // Unique name based on the 'text' property. + Node, // Unique name based on the node in the 'original' property. + } + export interface Identifier extends PrimaryExpression { kind: SyntaxKind.Identifier; text: string; // Text of identifier (with escapes converted to characters) @@ -572,14 +581,7 @@ resolvedSymbol: Symbol; } - export const enum GeneratedIdentifierKind { - None, // Not automatically generated. - Auto, // Automatically generated identifier. - Loop, // Automatically generated identifier with a preference for '_i'. - Unique, // Unique name based on the 'text' property. - Node, // Unique name based on the node in the 'original' property. - } - + /*@internal*/ export interface GeneratedIdentifier extends Identifier { autoGenerateKind: GeneratedIdentifierKind.Auto | GeneratedIdentifierKind.Loop @@ -3909,40 +3911,38 @@ /* @internal */ export type Transformer = (context: TransformationContext) => (node: SourceFile) => SourceFile; - export interface EmitTextWriter { - write(s: string): void; - writeTextOfNode(text: string, node: Node): void; - writeLine(): void; - increaseIndent(): void; - decreaseIndent(): void; - getText(): string; - rawWrite(s: string): void; - writeLiteral(s: string): void; - getTextPos(): number; - getLine(): number; - getColumn(): number; - getIndent(): number; - isAtStartOfLine(): boolean; - reset(): void; + export interface Printer { + printNode(hint: EmitHint, node: Node, sourceFile: SourceFile): string; + printFile(sourceFile: SourceFile): string; + printBundle(bundle: Bundle): string; } + /*@internal*/ export interface Printer { - printNode(hint: EmitHint, node: Node, sourceFile: SourceFile): void; - printFile(sourceFile: SourceFile): void; - printBundle(bundle: Bundle): void; + writeNode(hint: EmitHint, node: Node, sourceFile: SourceFile, writer: EmitTextWriter): void; + writeFile(sourceFile: SourceFile, writer: EmitTextWriter): void; + writeBundle(bundle: Bundle, writer: EmitTextWriter): void; + } + + export interface PrintHandlers { + hasGlobalName?: (name: string) => boolean; + onEmitNode?: (hint: EmitHint, node: Node, emitCallback: (hint: EmitHint, node: Node) => void) => void; + onSubstituteNode?: (hint: EmitHint, node: Node, emitCallback: (hint: EmitHint, node: Node) => void) => void; + /*@internal*/ onEmitSourceMapOfNode?: (hint: EmitHint, node: Node, emitCallback: (hint: EmitHint, node: Node) => void) => void; + /*@internal*/ onEmitSourceMapOfToken?: (node: Node, token: SyntaxKind, pos: number, emitCallback: (token: SyntaxKind, pos: number) => number) => number; + /*@internal*/ onEmitSourceMapOfPosition?: (pos: number) => void; + /*@internal*/ onEmitHelpers?: (node: Node, writeLines: (text: string) => void) => void; + /*@internal*/ onSetSourceFile?: (node: SourceFile) => void; } export interface PrinterOptions { - hasGlobalName?: (name: string) => boolean; - onEmitSourceMapOfNode?: (hint: EmitHint, node: Node, emitCallback: (hint: EmitHint, node: Node) => void) => void; - onEmitSourceMapOfToken?: (node: Node, token: SyntaxKind, pos: number, emitCallback: (token: SyntaxKind, pos: number) => number) => number; - onEmitCommentsOfNode?: (hint: EmitHint, node: Node, emitCallback: (hint: EmitHint, node: Node) => void) => void; - onEmitDetachedCommentsOfNode?: (node: Node, detachedRange: TextRange, emitCallback: (node: Node) => void) => void; - onEmitTrailingCommentsOfPosition?: (pos: number) => void; - onEmitNode?: (hint: EmitHint, node: Node, emitCallback: (hint: EmitHint, node: Node) => void) => void; - onEmitHelpers?: (node: Node, writeLines: (text: string) => void) => void; - onSetSourceFile?: (node: SourceFile) => void; - onSubstituteNode?: (hint: EmitHint, node: Node, emitCallback: (hint: EmitHint, node: Node) => void) => void; + target?: ScriptTarget; + module?: ModuleKind; + removeComments?: boolean; + newLine?: NewLineKind; + /*@internal*/ sourceMap?: boolean; + /*@internal*/ inlineSourceMap?: boolean; + /*@internal*/ extendedDiagnostics?: boolean; } export interface TextSpan { diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index 5c92bfa65cc..8d85ebeca99 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -2439,6 +2439,23 @@ namespace ts { s; } + export interface EmitTextWriter { + write(s: string): void; + writeTextOfNode(text: string, node: Node): void; + writeLine(): void; + increaseIndent(): void; + decreaseIndent(): void; + getText(): string; + rawWrite(s: string): void; + writeLiteral(s: string): void; + getTextPos(): number; + getLine(): number; + getColumn(): number; + getIndent(): number; + isAtStartOfLine(): boolean; + reset(): void; + } + const indentStrings: string[] = ["", " "]; export function getIndentString(level: number) { if (indentStrings[level] === undefined) { @@ -3215,7 +3232,7 @@ namespace ts { const carriageReturnLineFeed = "\r\n"; const lineFeed = "\n"; - export function getNewLineCharacter(options: CompilerOptions): string { + export function getNewLineCharacter(options: CompilerOptions | PrinterOptions): string { if (options.newLine === NewLineKind.CarriageReturnLineFeed) { return carriageReturnLineFeed; } diff --git a/src/harness/tsconfig.json b/src/harness/tsconfig.json index d7bb935db89..ebd07118cc5 100644 --- a/src/harness/tsconfig.json +++ b/src/harness/tsconfig.json @@ -37,7 +37,6 @@ "../compiler/comments.ts", "../compiler/sourcemap.ts", "../compiler/declarationEmitter.ts", - "../compiler/printer.ts", "../compiler/emitter.ts", "../compiler/program.ts", "../compiler/commandLineParser.ts", diff --git a/src/services/tsconfig.json b/src/services/tsconfig.json index 493f3b45f93..b60e00292f5 100644 --- a/src/services/tsconfig.json +++ b/src/services/tsconfig.json @@ -34,7 +34,6 @@ "../compiler/comments.ts", "../compiler/sourcemap.ts", "../compiler/declarationEmitter.ts", - "../compiler/printer.ts", "../compiler/emitter.ts", "../compiler/program.ts", "../compiler/commandLineParser.ts", From f0563ac2874190ef79549f17fdcf1da883add655 Mon Sep 17 00:00:00 2001 From: Ron Buckton Date: Mon, 30 Jan 2017 13:40:42 -0800 Subject: [PATCH 05/58] Printer API unit tests --- Jakefile.js | 1 + src/compiler/core.ts | 2 +- src/compiler/emitter.ts | 66 ++++--------- src/compiler/types.ts | 1 - src/harness/tsconfig.json | 3 +- src/harness/unittests/printer.ts | 97 +++++++++++++++++++ .../printsBundleCorrectly.default.js | 6 ++ .../printsBundleCorrectly.removeComments.js | 4 + .../printerApi/printsFileCorrectly.default.js | 25 +++++ .../printsFileCorrectly.removeComments.js | 17 ++++ .../printerApi/printsNodeCorrectly.class.js | 3 + 11 files changed, 173 insertions(+), 52 deletions(-) create mode 100644 src/harness/unittests/printer.ts create mode 100644 tests/baselines/reference/printerApi/printsBundleCorrectly.default.js create mode 100644 tests/baselines/reference/printerApi/printsBundleCorrectly.removeComments.js create mode 100644 tests/baselines/reference/printerApi/printsFileCorrectly.default.js create mode 100644 tests/baselines/reference/printerApi/printsFileCorrectly.removeComments.js create mode 100644 tests/baselines/reference/printerApi/printsNodeCorrectly.class.js diff --git a/Jakefile.js b/Jakefile.js index 3ee8476c842..0b3a26dbb77 100644 --- a/Jakefile.js +++ b/Jakefile.js @@ -269,6 +269,7 @@ var harnessSources = harnessCoreSources.concat([ "projectErrors.ts", "matchFiles.ts", "initializeTSConfig.ts", + "printer.ts", ].map(function (f) { return path.join(unittestsDirectory, f); })).concat([ diff --git a/src/compiler/core.ts b/src/compiler/core.ts index b8097acaa71..304fba69b26 100644 --- a/src/compiler/core.ts +++ b/src/compiler/core.ts @@ -1451,7 +1451,7 @@ namespace ts { return compilerOptions.target || ScriptTarget.ES3; } - export function getEmitModuleKind(compilerOptions: CompilerOptions | PrinterOptions) { + export function getEmitModuleKind(compilerOptions: CompilerOptions) { return typeof compilerOptions.module === "number" ? compilerOptions.module : getEmitScriptTarget(compilerOptions) >= ScriptTarget.ES2015 ? ModuleKind.ES2015 : ModuleKind.CommonJS; diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index b3bd594ae88..f20a7944a0f 100644 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -12,6 +12,7 @@ namespace ts { // targetSourceFile is when users only want one file in entire project to be emitted. This is used in compileOnSave feature export function emitFiles(resolver: EmitResolver, host: EmitHost, targetSourceFile: SourceFile, emitOnlyDtsFiles?: boolean): EmitResult { const compilerOptions = host.getCompilerOptions(); + const moduleKind = getEmitModuleKind(compilerOptions); const sourceMapDataList: SourceMapData[] = compilerOptions.sourceMap || compilerOptions.inlineSourceMap ? [] : undefined; const emittedFilesList: string[] = compilerOptions.listEmittedFiles ? [] : undefined; const emitterDiagnostics = createDiagnosticCollection(); @@ -147,6 +148,10 @@ namespace ts { function emitHelpers(node: Node, writeLines: (text: string) => void) { let helpersEmitted = false; const bundle = node.kind === SyntaxKind.Bundle ? node : undefined; + if (bundle && moduleKind === ModuleKind.None) { + return; + } + const numNodes = bundle ? bundle.sourceFiles.length : 1; for (let i = 0; i < numNodes; i++) { const currentNode = bundle ? bundle.sourceFiles[i] : node; @@ -201,7 +206,6 @@ namespace ts { const newLine = getNewLineCharacter(printerOptions); const languageVersion = getEmitScriptTarget(printerOptions); - const moduleKind = getEmitModuleKind(printerOptions); const comments = createCommentWriter(printerOptions, onEmitSourceMapOfPosition); const { emitNodeWithComments, @@ -257,9 +261,7 @@ namespace ts { function writeBundle(bundle: Bundle, output: EmitTextWriter) { const previousWriter = writer; setWriter(output); - if (moduleKind) { - emitHelpersIndirect(bundle); - } + emitHelpersIndirect(bundle); for (const sourceFile of bundle.sourceFiles) { print(EmitHint.SourceFile, sourceFile, sourceFile); } @@ -280,11 +282,8 @@ namespace ts { } function endPrint() { - const text = writer.getText(); - if (writer === ownWriter) { - writer.reset(); - } - + const text = ownWriter.getText(); + ownWriter.reset(); return text; } @@ -385,6 +384,15 @@ namespace ts { function pipelineEmitUnspecified(node: Node): void { const kind = node.kind; + + // Reserved words + // Strict mode reserved words + // Contextual keywords + if (isKeyword(kind)) { + writeTokenText(kind); + return; + } + switch (kind) { // Pseudo-literals case SyntaxKind.TemplateHead: @@ -396,46 +404,6 @@ namespace ts { case SyntaxKind.Identifier: return emitIdentifier(node); - // Reserved words - case SyntaxKind.ConstKeyword: - case SyntaxKind.DefaultKeyword: - case SyntaxKind.ExportKeyword: - case SyntaxKind.VoidKeyword: - - // Strict mode reserved words - case SyntaxKind.PrivateKeyword: - case SyntaxKind.ProtectedKeyword: - case SyntaxKind.PublicKeyword: - case SyntaxKind.StaticKeyword: - - // Contextual keywords - case SyntaxKind.AbstractKeyword: - case SyntaxKind.AsKeyword: - case SyntaxKind.AnyKeyword: - case SyntaxKind.AsyncKeyword: - case SyntaxKind.AwaitKeyword: - case SyntaxKind.BooleanKeyword: - case SyntaxKind.ConstructorKeyword: - case SyntaxKind.DeclareKeyword: - case SyntaxKind.GetKeyword: - case SyntaxKind.IsKeyword: - case SyntaxKind.ModuleKeyword: - case SyntaxKind.NamespaceKeyword: - case SyntaxKind.NeverKeyword: - case SyntaxKind.ReadonlyKeyword: - case SyntaxKind.RequireKeyword: - case SyntaxKind.NumberKeyword: - case SyntaxKind.SetKeyword: - case SyntaxKind.StringKeyword: - case SyntaxKind.SymbolKeyword: - case SyntaxKind.TypeKeyword: - case SyntaxKind.UndefinedKeyword: - case SyntaxKind.FromKeyword: - case SyntaxKind.GlobalKeyword: - case SyntaxKind.OfKeyword: - writeTokenText(kind); - return; - // Parse tree nodes // Names diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 99cdca407b6..7e097ef40b1 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -3937,7 +3937,6 @@ export interface PrinterOptions { target?: ScriptTarget; - module?: ModuleKind; removeComments?: boolean; newLine?: NewLineKind; /*@internal*/ sourceMap?: boolean; diff --git a/src/harness/tsconfig.json b/src/harness/tsconfig.json index ebd07118cc5..bea688d358b 100644 --- a/src/harness/tsconfig.json +++ b/src/harness/tsconfig.json @@ -118,6 +118,7 @@ "./unittests/initializeTSConfig.ts", "./unittests/compileOnSave.ts", "./unittests/typingsInstaller.ts", - "./unittests/projectErrors.ts" + "./unittests/projectErrors.ts", + "./unittests/printer.ts" ] } diff --git a/src/harness/unittests/printer.ts b/src/harness/unittests/printer.ts new file mode 100644 index 00000000000..2496a880bc5 --- /dev/null +++ b/src/harness/unittests/printer.ts @@ -0,0 +1,97 @@ +/// +/// + +namespace ts { + describe("PrinterAPI", () => { + function makePrintsCorrectly(prefix: string) { + return function printsCorrectly(name: string, options: PrinterOptions, printCallback: (printer: Printer) => string) { + it(name, () => { + Harness.Baseline.runBaseline(`printerApi/${prefix}.${name}.js`, () => + printCallback(createPrinter({ newLine: NewLineKind.CarriageReturnLineFeed, ...options }))); + }); + } + } + + describe("printFile", () => { + const printsCorrectly = makePrintsCorrectly("printsFileCorrectly"); + const sourceFile = createSourceFile("source.ts", ` + interface A { + // comment1 + readonly prop?: T; + + // comment2 + method(): void; + + // comment3 + new (): A; + + // comment4 + (): A; + } + + // comment5 + type B = number | string | object; + type C = A & { x: string; }; // comment6 + + // comment7 + enum E1 { + // comment8 + first + } + + const enum E2 { + second + } + + // comment9 + console.log(1 + 2); + `, ScriptTarget.ES2015); + + printsCorrectly("default", {}, printer => printer.printFile(sourceFile)); + printsCorrectly("removeComments", { removeComments: true }, printer => printer.printFile(sourceFile)); + }); + + describe("printBundle", () => { + const printsCorrectly = makePrintsCorrectly("printsBundleCorrectly"); + const bundle = createBundle([ + createSourceFile("a.ts", ` + /*! [a.ts] */ + + // comment0 + const a = 1; + `, ScriptTarget.ES2015), + createSourceFile("b.ts", ` + /*! [b.ts] */ + + // comment1 + const b = 2; + `, ScriptTarget.ES2015) + ]); + printsCorrectly("default", {}, printer => printer.printBundle(bundle)); + printsCorrectly("removeComments", { removeComments: true }, printer => printer.printBundle(bundle)); + }); + + describe("printNode", () => { + const printsCorrectly = makePrintsCorrectly("printsNodeCorrectly"); + const sourceFile = createSourceFile("source.ts", "", ScriptTarget.ES2015); + const syntheticNode = createClassDeclaration( + undefined, + undefined, + /*name*/ createIdentifier("C"), + undefined, + undefined, + createNodeArray([ + createProperty( + undefined, + createNodeArray([createToken(SyntaxKind.PublicKeyword)]), + createIdentifier("prop"), + undefined, + undefined, + undefined + ) + ]) + ); + printsCorrectly("class", {}, printer => printer.printNode(EmitHint.Unspecified, syntheticNode, sourceFile)); + }); + }); +} diff --git a/tests/baselines/reference/printerApi/printsBundleCorrectly.default.js b/tests/baselines/reference/printerApi/printsBundleCorrectly.default.js new file mode 100644 index 00000000000..2d86cc0c09c --- /dev/null +++ b/tests/baselines/reference/printerApi/printsBundleCorrectly.default.js @@ -0,0 +1,6 @@ +/*! [a.ts] */ +// comment0 +const a = 1; +/*! [b.ts] */ +// comment1 +const b = 2; diff --git a/tests/baselines/reference/printerApi/printsBundleCorrectly.removeComments.js b/tests/baselines/reference/printerApi/printsBundleCorrectly.removeComments.js new file mode 100644 index 00000000000..22b03719cf3 --- /dev/null +++ b/tests/baselines/reference/printerApi/printsBundleCorrectly.removeComments.js @@ -0,0 +1,4 @@ +/*! [a.ts] */ +const a = 1; +/*! [b.ts] */ +const b = 2; diff --git a/tests/baselines/reference/printerApi/printsFileCorrectly.default.js b/tests/baselines/reference/printerApi/printsFileCorrectly.default.js new file mode 100644 index 00000000000..9bff9d656b3 --- /dev/null +++ b/tests/baselines/reference/printerApi/printsFileCorrectly.default.js @@ -0,0 +1,25 @@ +interface A { + // comment1 + readonly prop?: T; + // comment2 + method(): void; + // comment3 + new (): A; + // comment4 + (): A; +} +// comment5 +type B = number | string | object; +type C = A & { + x: string; +}; // comment6 +// comment7 +enum E1 { + // comment8 + first +} +const enum E2 { + second +} +// comment9 +console.log(1 + 2); diff --git a/tests/baselines/reference/printerApi/printsFileCorrectly.removeComments.js b/tests/baselines/reference/printerApi/printsFileCorrectly.removeComments.js new file mode 100644 index 00000000000..b511aff5e78 --- /dev/null +++ b/tests/baselines/reference/printerApi/printsFileCorrectly.removeComments.js @@ -0,0 +1,17 @@ +interface A { + readonly prop?: T; + method(): void; + new (): A; + (): A; +} +type B = number | string | object; +type C = A & { + x: string; +}; +enum E1 { + first +} +const enum E2 { + second +} +console.log(1 + 2); diff --git a/tests/baselines/reference/printerApi/printsNodeCorrectly.class.js b/tests/baselines/reference/printerApi/printsNodeCorrectly.class.js new file mode 100644 index 00000000000..fa19e836fed --- /dev/null +++ b/tests/baselines/reference/printerApi/printsNodeCorrectly.class.js @@ -0,0 +1,3 @@ +class C { + public prop; +} \ No newline at end of file From 64ff691a2e9c2cf4f5eb651bffc2a19d82adccd3 Mon Sep 17 00:00:00 2001 From: Ron Buckton Date: Mon, 30 Jan 2017 14:21:52 -0800 Subject: [PATCH 06/58] Move EmitTextWriter to types.ts --- src/compiler/types.ts | 28 +++++++++++++++++++++------- src/compiler/utilities.ts | 17 ----------------- 2 files changed, 21 insertions(+), 24 deletions(-) diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 7e097ef40b1..03098fd4129 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -3915,13 +3915,9 @@ printNode(hint: EmitHint, node: Node, sourceFile: SourceFile): string; printFile(sourceFile: SourceFile): string; printBundle(bundle: Bundle): string; - } - - /*@internal*/ - export interface Printer { - writeNode(hint: EmitHint, node: Node, sourceFile: SourceFile, writer: EmitTextWriter): void; - writeFile(sourceFile: SourceFile, writer: EmitTextWriter): void; - writeBundle(bundle: Bundle, writer: EmitTextWriter): void; + /*@internal*/ writeNode(hint: EmitHint, node: Node, sourceFile: SourceFile, writer: EmitTextWriter): void; + /*@internal*/ writeFile(sourceFile: SourceFile, writer: EmitTextWriter): void; + /*@internal*/ writeBundle(bundle: Bundle, writer: EmitTextWriter): void; } export interface PrintHandlers { @@ -3944,6 +3940,24 @@ /*@internal*/ extendedDiagnostics?: boolean; } + /*@internal*/ + export interface EmitTextWriter { + write(s: string): void; + writeTextOfNode(text: string, node: Node): void; + writeLine(): void; + increaseIndent(): void; + decreaseIndent(): void; + getText(): string; + rawWrite(s: string): void; + writeLiteral(s: string): void; + getTextPos(): number; + getLine(): number; + getColumn(): number; + getIndent(): number; + isAtStartOfLine(): boolean; + reset(): void; + } + export interface TextSpan { start: number; length: number; diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index 8d85ebeca99..a2c5cbd15a3 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -2439,23 +2439,6 @@ namespace ts { s; } - export interface EmitTextWriter { - write(s: string): void; - writeTextOfNode(text: string, node: Node): void; - writeLine(): void; - increaseIndent(): void; - decreaseIndent(): void; - getText(): string; - rawWrite(s: string): void; - writeLiteral(s: string): void; - getTextPos(): number; - getLine(): number; - getColumn(): number; - getIndent(): number; - isAtStartOfLine(): boolean; - reset(): void; - } - const indentStrings: string[] = ["", " "]; export function getIndentString(level: number) { if (indentStrings[level] === undefined) { From 7e7057a89d6780f0b093fef4be26c4ddeb4c62ef Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Mon, 30 Jan 2017 16:53:31 -0800 Subject: [PATCH 07/58] Empty object type assignable to mapped type with optional properties --- src/compiler/checker.ts | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 780bda03b0a..26c27cb3be2 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -7687,7 +7687,7 @@ namespace ts { function isKnownProperty(type: Type, name: string): boolean { if (type.flags & TypeFlags.Object) { const resolved = resolveStructuredTypeMembers(type); - if ((relation === assignableRelation || relation === comparableRelation) && (type === globalObjectType || isEmptyObjectType(resolved)) || + if ((relation === assignableRelation || relation === comparableRelation) && (type === globalObjectType || isEmptyResolvedType(resolved)) || resolved.stringIndexInfo || (resolved.numberIndexInfo && isNumericLiteralName(name)) || getPropertyOfType(type, name)) { @@ -7704,7 +7704,7 @@ namespace ts { return false; } - function isEmptyObjectType(t: ResolvedType) { + function isEmptyResolvedType(t: ResolvedType) { return t.properties.length === 0 && t.callSignatures.length === 0 && t.constructSignatures.length === 0 && @@ -7712,6 +7712,10 @@ namespace ts { !t.numberIndexInfo; } + function isEmptyObjectType(type: Type) { + return type.flags & TypeFlags.Object && isEmptyResolvedType(resolveStructuredTypeMembers(type)); + } + function hasExcessProperties(source: FreshObjectLiteralType, target: Type, reportErrors: boolean): boolean { if (maybeTypeOfKind(target, TypeFlags.Object) && !(getObjectFlags(target) & ObjectFlags.ObjectLiteralPatternWithComputedProperties)) { for (const prop of getPropertiesOfObjectType(source)) { @@ -7925,10 +7929,14 @@ namespace ts { } } } + else if ((target).declaration.questionToken && isEmptyObjectType(source)) { + return Ternary.True; + + } } else if (relation !== identityRelation) { const resolved = resolveStructuredTypeMembers(target); - if (isEmptyObjectType(resolved) || resolved.stringIndexInfo && resolved.stringIndexInfo.type.flags & TypeFlags.Any) { + if (isEmptyResolvedType(resolved) || resolved.stringIndexInfo && resolved.stringIndexInfo.type.flags & TypeFlags.Any) { return Ternary.True; } } From 647e1836c3a8898d85b5c5a9371cd9bb98eec2b1 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Mon, 30 Jan 2017 16:53:43 -0800 Subject: [PATCH 08/58] Add tests --- .../types/mapped/mappedTypesAndObjects.ts | 24 +++++++++++++------ 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/tests/cases/conformance/types/mapped/mappedTypesAndObjects.ts b/tests/cases/conformance/types/mapped/mappedTypesAndObjects.ts index 8023f6e7d8d..b3530b46965 100644 --- a/tests/cases/conformance/types/mapped/mappedTypesAndObjects.ts +++ b/tests/cases/conformance/types/mapped/mappedTypesAndObjects.ts @@ -13,23 +13,33 @@ function f2(x: Partial, y: Readonly) { obj = y; } +function f3(x: Partial) { + x = {}; +} + // Repro from #12900 interface Base { - foo: { [key: string]: any }; - bar: any; - baz: any; + foo: { [key: string]: any }; + bar: any; + baz: any; } interface E1 extends Base { - foo: T; + foo: T; } interface Something { name: string, value: string }; interface E2 extends Base { - foo: Partial; // or other mapped type + foo: Partial; // or other mapped type } interface E3 extends Base { - foo: Partial; // or other mapped type -} \ No newline at end of file + foo: Partial; // or other mapped type +} + +// Repro from #13747 + +class Form { + private values: {[P in keyof T]?: T[P]} = {} +} From 86591016186b41fc8b9db73fbbe8bdd3036c638d Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Mon, 30 Jan 2017 16:57:11 -0800 Subject: [PATCH 09/58] Accept new baselines --- .../reference/mappedTypesAndObjects.js | 39 +++++++-- .../reference/mappedTypesAndObjects.symbols | 82 ++++++++++++------- .../reference/mappedTypesAndObjects.types | 41 ++++++++-- 3 files changed, 121 insertions(+), 41 deletions(-) diff --git a/tests/baselines/reference/mappedTypesAndObjects.js b/tests/baselines/reference/mappedTypesAndObjects.js index 53b39209693..f320cc9624e 100644 --- a/tests/baselines/reference/mappedTypesAndObjects.js +++ b/tests/baselines/reference/mappedTypesAndObjects.js @@ -12,26 +12,37 @@ function f2(x: Partial, y: Readonly) { obj = y; } +function f3(x: Partial) { + x = {}; +} + // Repro from #12900 interface Base { - foo: { [key: string]: any }; - bar: any; - baz: any; + foo: { [key: string]: any }; + bar: any; + baz: any; } interface E1 extends Base { - foo: T; + foo: T; } interface Something { name: string, value: string }; interface E2 extends Base { - foo: Partial; // or other mapped type + foo: Partial; // or other mapped type } interface E3 extends Base { - foo: Partial; // or other mapped type -} + foo: Partial; // or other mapped type +} + +// Repro from #13747 + +class Form { + private values: {[P in keyof T]?: T[P]} = {} +} + //// [mappedTypesAndObjects.js] function f1(x, y) { @@ -44,12 +55,23 @@ function f2(x, y) { obj = x; obj = y; } +function f3(x) { + x = {}; +} ; +// Repro from #13747 +var Form = (function () { + function Form() { + this.values = {}; + } + return Form; +}()); //// [mappedTypesAndObjects.d.ts] declare function f1(x: Partial, y: Readonly): void; declare function f2(x: Partial, y: Readonly): void; +declare function f3(x: Partial): void; interface Base { foo: { [key: string]: any; @@ -70,3 +92,6 @@ interface E2 extends Base { interface E3 extends Base { foo: Partial; } +declare class Form { + private values; +} diff --git a/tests/baselines/reference/mappedTypesAndObjects.symbols b/tests/baselines/reference/mappedTypesAndObjects.symbols index 1690f1b6b04..6fb5d720fb3 100644 --- a/tests/baselines/reference/mappedTypesAndObjects.symbols +++ b/tests/baselines/reference/mappedTypesAndObjects.symbols @@ -45,54 +45,80 @@ function f2(x: Partial, y: Readonly) { >y : Symbol(y, Decl(mappedTypesAndObjects.ts, 7, 29)) } +function f3(x: Partial) { +>f3 : Symbol(f3, Decl(mappedTypesAndObjects.ts, 11, 1)) +>T : Symbol(T, Decl(mappedTypesAndObjects.ts, 13, 12)) +>x : Symbol(x, Decl(mappedTypesAndObjects.ts, 13, 15)) +>Partial : Symbol(Partial, Decl(lib.d.ts, --, --)) +>T : Symbol(T, Decl(mappedTypesAndObjects.ts, 13, 12)) + + x = {}; +>x : Symbol(x, Decl(mappedTypesAndObjects.ts, 13, 15)) +} + // Repro from #12900 interface Base { ->Base : Symbol(Base, Decl(mappedTypesAndObjects.ts, 11, 1)) +>Base : Symbol(Base, Decl(mappedTypesAndObjects.ts, 15, 1)) - foo: { [key: string]: any }; ->foo : Symbol(Base.foo, Decl(mappedTypesAndObjects.ts, 15, 16)) ->key : Symbol(key, Decl(mappedTypesAndObjects.ts, 16, 11)) + foo: { [key: string]: any }; +>foo : Symbol(Base.foo, Decl(mappedTypesAndObjects.ts, 19, 16)) +>key : Symbol(key, Decl(mappedTypesAndObjects.ts, 20, 12)) - bar: any; ->bar : Symbol(Base.bar, Decl(mappedTypesAndObjects.ts, 16, 31)) + bar: any; +>bar : Symbol(Base.bar, Decl(mappedTypesAndObjects.ts, 20, 32)) - baz: any; ->baz : Symbol(Base.baz, Decl(mappedTypesAndObjects.ts, 17, 12)) + baz: any; +>baz : Symbol(Base.baz, Decl(mappedTypesAndObjects.ts, 21, 13)) } interface E1 extends Base { ->E1 : Symbol(E1, Decl(mappedTypesAndObjects.ts, 19, 1)) ->T : Symbol(T, Decl(mappedTypesAndObjects.ts, 21, 13)) ->Base : Symbol(Base, Decl(mappedTypesAndObjects.ts, 11, 1)) +>E1 : Symbol(E1, Decl(mappedTypesAndObjects.ts, 23, 1)) +>T : Symbol(T, Decl(mappedTypesAndObjects.ts, 25, 13)) +>Base : Symbol(Base, Decl(mappedTypesAndObjects.ts, 15, 1)) - foo: T; ->foo : Symbol(E1.foo, Decl(mappedTypesAndObjects.ts, 21, 30)) ->T : Symbol(T, Decl(mappedTypesAndObjects.ts, 21, 13)) + foo: T; +>foo : Symbol(E1.foo, Decl(mappedTypesAndObjects.ts, 25, 30)) +>T : Symbol(T, Decl(mappedTypesAndObjects.ts, 25, 13)) } interface Something { name: string, value: string }; ->Something : Symbol(Something, Decl(mappedTypesAndObjects.ts, 23, 1)) ->name : Symbol(Something.name, Decl(mappedTypesAndObjects.ts, 25, 21)) ->value : Symbol(Something.value, Decl(mappedTypesAndObjects.ts, 25, 35)) +>Something : Symbol(Something, Decl(mappedTypesAndObjects.ts, 27, 1)) +>name : Symbol(Something.name, Decl(mappedTypesAndObjects.ts, 29, 21)) +>value : Symbol(Something.value, Decl(mappedTypesAndObjects.ts, 29, 35)) interface E2 extends Base { ->E2 : Symbol(E2, Decl(mappedTypesAndObjects.ts, 25, 52)) ->Base : Symbol(Base, Decl(mappedTypesAndObjects.ts, 11, 1)) +>E2 : Symbol(E2, Decl(mappedTypesAndObjects.ts, 29, 52)) +>Base : Symbol(Base, Decl(mappedTypesAndObjects.ts, 15, 1)) - foo: Partial; // or other mapped type ->foo : Symbol(E2.foo, Decl(mappedTypesAndObjects.ts, 26, 27)) + foo: Partial; // or other mapped type +>foo : Symbol(E2.foo, Decl(mappedTypesAndObjects.ts, 30, 27)) >Partial : Symbol(Partial, Decl(lib.d.ts, --, --)) ->Something : Symbol(Something, Decl(mappedTypesAndObjects.ts, 23, 1)) +>Something : Symbol(Something, Decl(mappedTypesAndObjects.ts, 27, 1)) } interface E3 extends Base { ->E3 : Symbol(E3, Decl(mappedTypesAndObjects.ts, 28, 1)) ->T : Symbol(T, Decl(mappedTypesAndObjects.ts, 30, 13)) ->Base : Symbol(Base, Decl(mappedTypesAndObjects.ts, 11, 1)) +>E3 : Symbol(E3, Decl(mappedTypesAndObjects.ts, 32, 1)) +>T : Symbol(T, Decl(mappedTypesAndObjects.ts, 34, 13)) +>Base : Symbol(Base, Decl(mappedTypesAndObjects.ts, 15, 1)) - foo: Partial; // or other mapped type ->foo : Symbol(E3.foo, Decl(mappedTypesAndObjects.ts, 30, 30)) + foo: Partial; // or other mapped type +>foo : Symbol(E3.foo, Decl(mappedTypesAndObjects.ts, 34, 30)) >Partial : Symbol(Partial, Decl(lib.d.ts, --, --)) ->T : Symbol(T, Decl(mappedTypesAndObjects.ts, 30, 13)) +>T : Symbol(T, Decl(mappedTypesAndObjects.ts, 34, 13)) } + +// Repro from #13747 + +class Form { +>Form : Symbol(Form, Decl(mappedTypesAndObjects.ts, 36, 1)) +>T : Symbol(T, Decl(mappedTypesAndObjects.ts, 40, 11)) + + private values: {[P in keyof T]?: T[P]} = {} +>values : Symbol(Form.values, Decl(mappedTypesAndObjects.ts, 40, 15)) +>P : Symbol(P, Decl(mappedTypesAndObjects.ts, 41, 22)) +>T : Symbol(T, Decl(mappedTypesAndObjects.ts, 40, 11)) +>T : Symbol(T, Decl(mappedTypesAndObjects.ts, 40, 11)) +>P : Symbol(P, Decl(mappedTypesAndObjects.ts, 41, 22)) +} + diff --git a/tests/baselines/reference/mappedTypesAndObjects.types b/tests/baselines/reference/mappedTypesAndObjects.types index e6f8e53f558..75f71082f31 100644 --- a/tests/baselines/reference/mappedTypesAndObjects.types +++ b/tests/baselines/reference/mappedTypesAndObjects.types @@ -49,19 +49,32 @@ function f2(x: Partial, y: Readonly) { >y : Readonly } +function f3(x: Partial) { +>f3 : (x: Partial) => void +>T : T +>x : Partial +>Partial : Partial +>T : T + + x = {}; +>x = {} : {} +>x : Partial +>{} : {} +} + // Repro from #12900 interface Base { >Base : Base - foo: { [key: string]: any }; + foo: { [key: string]: any }; >foo : { [key: string]: any; } >key : string - bar: any; + bar: any; >bar : any - baz: any; + baz: any; >baz : any } @@ -70,7 +83,7 @@ interface E1 extends Base { >T : T >Base : Base - foo: T; + foo: T; >foo : T >T : T } @@ -84,7 +97,7 @@ interface E2 extends Base { >E2 : E2 >Base : Base - foo: Partial; // or other mapped type + foo: Partial; // or other mapped type >foo : Partial >Partial : Partial >Something : Something @@ -95,8 +108,24 @@ interface E3 extends Base { >T : T >Base : Base - foo: Partial; // or other mapped type + foo: Partial; // or other mapped type >foo : Partial >Partial : Partial >T : T } + +// Repro from #13747 + +class Form { +>Form : Form +>T : T + + private values: {[P in keyof T]?: T[P]} = {} +>values : { [P in keyof T]?: T[P] | undefined; } +>P : P +>T : T +>T : T +>P : P +>{} : {} +} + From 58cb9a7f08f73b19efb4db5e7bc07ac126a0759a Mon Sep 17 00:00:00 2001 From: Andy Hanson Date: Mon, 30 Jan 2017 07:49:17 -0800 Subject: [PATCH 10/58] Use "ts2.2" (or "ts2.3", etc.) NPM tag in typingsInstaller --- src/harness/unittests/typingsInstaller.ts | 18 ++++++++++-------- .../typingsInstaller/typingsInstaller.ts | 10 ++++++++-- 2 files changed, 18 insertions(+), 10 deletions(-) diff --git a/src/harness/unittests/typingsInstaller.ts b/src/harness/unittests/typingsInstaller.ts index d4956a387ee..2b79141c3e3 100644 --- a/src/harness/unittests/typingsInstaller.ts +++ b/src/harness/unittests/typingsInstaller.ts @@ -44,6 +44,8 @@ namespace ts.projectSystem { }); } + import typingsName = server.typingsInstaller.typingsName; + describe("typingsInstaller", () => { it("configured projects (typings installed) 1", () => { const file1 = { @@ -519,32 +521,32 @@ namespace ts.projectSystem { const commander = { path: "/a/data/node_modules/@types/commander/index.d.ts", content: "declare const commander: { x: number }", - typings: "@types/commander" + typings: typingsName("commander") }; const jquery = { path: "/a/data/node_modules/@types/jquery/index.d.ts", content: "declare const jquery: { x: number }", - typings: "@types/jquery" + typings: typingsName("jquery") }; const lodash = { path: "/a/data/node_modules/@types/lodash/index.d.ts", content: "declare const lodash: { x: number }", - typings: "@types/lodash" + typings: typingsName("lodash") }; const cordova = { path: "/a/data/node_modules/@types/cordova/index.d.ts", content: "declare const cordova: { x: number }", - typings: "@types/cordova" + typings: typingsName("cordova") }; const grunt = { path: "/a/data/node_modules/@types/grunt/index.d.ts", content: "declare const grunt: { x: number }", - typings: "@types/grunt" + typings: typingsName("grunt") }; const gulp = { path: "/a/data/node_modules/@types/gulp/index.d.ts", content: "declare const gulp: { x: number }", - typings: "@types/gulp" + typings: typingsName("gulp") }; const host = createServerHost([lodashJs, commanderJs, file3]); @@ -554,7 +556,7 @@ namespace ts.projectSystem { } installWorker(_requestId: number, args: string[], _cwd: string, cb: TI.RequestCompletedAction): void { let typingFiles: (FileOrFolder & { typings: string })[] = []; - if (args.indexOf("@types/commander") >= 0) { + if (args.indexOf(typingsName("commander")) >= 0) { typingFiles = [commander, jquery, lodash, cordova]; } else { @@ -982,7 +984,7 @@ namespace ts.projectSystem { return; } if (response.kind === server.EventEndInstallTypes) { - assert.deepEqual(response.packagesToInstall, ["@types/commander"]); + assert.deepEqual(response.packagesToInstall, [typingsName("commander")]); seenTelemetryEvent = true; return; } diff --git a/src/server/typingsInstaller/typingsInstaller.ts b/src/server/typingsInstaller/typingsInstaller.ts index 1869c542a6e..e889f98789a 100644 --- a/src/server/typingsInstaller/typingsInstaller.ts +++ b/src/server/typingsInstaller/typingsInstaller.ts @@ -295,8 +295,7 @@ namespace ts.server.typingsInstaller { this.log.writeLine(`Installing typings ${JSON.stringify(typingsToInstall)}`); } const filteredTypings = this.filterTypings(typingsToInstall); - const scopedTypings = filteredTypings.map(x => `@types/${x}`); - if (scopedTypings.length === 0) { + if (filteredTypings.length === 0) { if (this.log.isEnabled()) { this.log.writeLine(`All typings are known to be missing or invalid - no need to go any further`); } @@ -316,6 +315,7 @@ namespace ts.server.typingsInstaller { projectName: req.projectName }); + const scopedTypings = filteredTypings.map(typingsName); this.installTypingsAsync(requestId, scopedTypings, cachePath, ok => { try { if (!ok) { @@ -429,4 +429,10 @@ namespace ts.server.typingsInstaller { protected abstract installWorker(requestId: number, args: string[], cwd: string, onRequestCompleted: RequestCompletedAction): void; protected abstract sendResponse(response: SetTypings | InvalidateCachedTypings | BeginInstallTypes | EndInstallTypes): void; } + + /* @internal */ + export function typingsName(packageName: string): string { + return `@types/${packageName}@ts${versionMajorMinor}`; + } + const versionMajorMinor = version.split(".").slice(0, 2).join("."); } \ No newline at end of file From 8515f7e2b56c39cbaee699125dc7363d5a819dc9 Mon Sep 17 00:00:00 2001 From: Andy Hanson Date: Fri, 27 Jan 2017 08:59:33 -0800 Subject: [PATCH 11/58] Change find-all-references tests to test for groups * Also always test for isWriteAccess and isDefinition --- src/harness/fourslash.ts | 121 +++++++++++++----- src/services/findAllReferences.ts | 19 +-- src/services/services.ts | 7 +- .../fourslash/ambientShorthandFindAllRefs.ts | 15 ++- ...cellationWhenfindingAllRefsOnDefinition.ts | 18 ++- .../findAllReferencesOfConstructor.ts | 6 +- ...dAllReferencesOfConstructor_badOverload.ts | 2 +- .../findAllRefsForComputedProperties.ts | 20 ++- .../findAllRefsForComputedProperties2.ts | 18 ++- .../fourslash/findAllRefsForDefaultExport.ts | 6 +- .../findAllRefsForDefaultExport01.ts | 7 +- .../findAllRefsForDefaultExport02.ts | 17 ++- .../findAllRefsForDefaultExport03.ts | 9 +- .../findAllRefsForDefaultExport04.ts | 23 ---- .../findAllRefsForDefaultExport05.ts | 23 ---- .../findAllRefsForDefaultExport06.ts | 23 ---- .../findAllRefsForDefaultExport07.ts | 16 --- .../findAllRefsForDefaultExport08.ts | 5 +- .../findAllRefsForFunctionExpression01.ts | 4 +- .../fourslash/findAllRefsForMappedType.ts | 18 ++- .../findAllRefsForObjectLiteralProperties.ts | 10 +- .../fourslash/findAllRefsForObjectSpread.ts | 17 ++- tests/cases/fourslash/findAllRefsForRest.ts | 4 +- .../findAllRefsForStringLiteralTypes.ts | 2 +- .../findAllRefsForUMDModuleAlias1.ts | 4 +- ...findAllRefsForVariableInExtendsClause01.ts | 4 +- ...findAllRefsForVariableInExtendsClause02.ts | 4 +- ...dAllRefsForVariableInImplementsClause01.ts | 3 +- .../fourslash/findAllRefsInClassExpression.ts | 12 +- .../findAllRefsInheritedProperties1.ts | 14 +- .../findAllRefsInheritedProperties2.ts | 10 +- .../findAllRefsInheritedProperties3.ts | 46 ++++--- .../findAllRefsInheritedProperties4.ts | 17 +-- .../findAllRefsInheritedProperties5.ts | 15 +-- .../fourslash/findAllRefsInsideTemplates1.ts | 4 +- .../fourslash/findAllRefsInsideTemplates2.ts | 4 +- .../fourslash/findAllRefsInsideWithBlock.ts | 6 +- ...lRefsObjectBindingElementPropertyName01.ts | 4 +- ...lRefsObjectBindingElementPropertyName02.ts | 4 +- ...lRefsObjectBindingElementPropertyName03.ts | 12 +- ...lRefsObjectBindingElementPropertyName04.ts | 13 +- ...lRefsObjectBindingElementPropertyName05.ts | 2 +- ...lRefsObjectBindingElementPropertyName06.ts | 21 ++- ...lRefsObjectBindingElementPropertyName07.ts | 10 +- ...lRefsObjectBindingElementPropertyName09.ts | 15 --- ...lRefsObjectBindingElementPropertyName10.ts | 4 +- .../findAllRefsOfConstructor_withModifier.ts | 3 +- .../fourslash/findAllRefsOnDecorators.ts | 4 +- .../fourslash/findAllRefsOnDefinition.ts | 10 +- .../fourslash/findAllRefsOnDefinition2.ts | 8 +- .../fourslash/findAllRefsOnImportAliases.ts | 11 +- .../fourslash/findAllRefsOnImportAliases2.ts | 16 ++- .../findAllRefsOnPrivateParameterProperty1.ts | 4 +- ...indAllRefsParameterPropertyDeclaration1.ts | 9 +- ...indAllRefsParameterPropertyDeclaration2.ts | 9 +- ...indAllRefsParameterPropertyDeclaration3.ts | 9 +- tests/cases/fourslash/findAllRefsPrimitive.ts | 2 +- ...sPropertyContextuallyTypedByTypeParam01.ts | 18 ++- .../cases/fourslash/findAllRefsThisKeyword.ts | 22 ++-- .../findAllRefsWithLeadingUnderscoreNames1.ts | 10 +- .../findAllRefsWithLeadingUnderscoreNames2.ts | 10 +- .../findAllRefsWithLeadingUnderscoreNames3.ts | 10 +- .../findAllRefsWithLeadingUnderscoreNames4.ts | 10 +- .../findAllRefsWithLeadingUnderscoreNames5.ts | 4 +- .../findAllRefsWithLeadingUnderscoreNames6.ts | 4 +- .../findAllRefsWithLeadingUnderscoreNames7.ts | 4 +- .../findAllRefsWithLeadingUnderscoreNames8.ts | 4 +- .../findAllRefsWithLeadingUnderscoreNames9.ts | 4 +- ...dAllRefsWithShorthandPropertyAssignment.ts | 21 +-- ...AllRefsWithShorthandPropertyAssignment2.ts | 20 ++- .../findReferencesAcrossMultipleProjects.ts | 8 +- .../fourslash/findReferencesAfterEdit.ts | 6 +- .../fourslash/findReferencesJSXTagName.ts | 8 +- .../fourslash/findReferencesJSXTagName2.ts | 6 +- tests/cases/fourslash/fourslash.ts | 16 +-- ...tOccurrencesIsDefinitionOfArrowFunction.ts | 6 +- ...OccurrencesIsDefinitionOfBindingPattern.ts | 4 +- .../getOccurrencesIsDefinitionOfClass.ts | 9 +- ...currencesIsDefinitionOfComputedProperty.ts | 12 +- .../getOccurrencesIsDefinitionOfEnum.ts | 6 +- .../getOccurrencesIsDefinitionOfExport.ts | 8 +- .../getOccurrencesIsDefinitionOfFunction.ts | 6 +- .../getOccurrencesIsDefinitionOfInterface.ts | 6 +- ...rencesIsDefinitionOfInterfaceClassMerge.ts | 13 +- .../getOccurrencesIsDefinitionOfNamespace.ts | 6 +- ...rencesIsDefinitionOfNumberNamedProperty.ts | 10 +- .../getOccurrencesIsDefinitionOfParameter.ts | 6 +- ...rencesIsDefinitionOfStringNamedProperty.ts | 10 +- .../getOccurrencesIsDefinitionOfTypeAlias.ts | 6 +- .../getOccurrencesIsDefinitionOfVariable.ts | 28 ++-- tests/cases/fourslash/hoverOverComment.ts | 2 +- tests/cases/fourslash/localGetReferences.ts | 66 ++++++---- tests/cases/fourslash/quickInfoForRequire.ts | 5 +- ...referenceInParameterPropertyDeclaration.ts | 21 ++- tests/cases/fourslash/referenceToClass.ts | 7 +- .../cases/fourslash/referencesBloomFilters.ts | 16 ++- .../fourslash/referencesBloomFilters2.ts | 16 ++- .../fourslash/referencesBloomFilters3.ts | 4 +- .../cases/fourslash/referencesForAmbients.ts | 16 +-- .../fourslash/referencesForClassLocal.ts | 4 +- .../fourslash/referencesForClassMembers.ts | 30 ++++- ...esForClassMembersExtendingAbstractClass.ts | 30 ++++- ...cesForClassMembersExtendingGenericClass.ts | 30 ++++- .../fourslash/referencesForClassParameter.ts | 10 +- ...ontextuallyTypedObjectLiteralProperties.ts | 28 ++-- ...ncesForContextuallyTypedUnionProperties.ts | 36 +++--- ...cesForContextuallyTypedUnionProperties2.ts | 26 ++-- tests/cases/fourslash/referencesForEnums.ts | 11 +- .../fourslash/referencesForExportedValues.ts | 4 +- .../referencesForExternalModuleNames.ts | 7 +- .../referencesForFunctionOverloads.ts | 6 +- .../referencesForFunctionParameter.ts | 6 +- tests/cases/fourslash/referencesForGlobals.ts | 4 +- .../cases/fourslash/referencesForGlobals2.ts | 4 +- .../cases/fourslash/referencesForGlobals3.ts | 4 +- .../cases/fourslash/referencesForGlobals4.ts | 4 +- .../cases/fourslash/referencesForGlobals5.ts | 4 +- .../referencesForGlobalsInExternalModule.ts | 18 ++- .../referencesForIllegalAssignment.ts | 10 +- tests/cases/fourslash/referencesForImports.ts | 8 +- .../fourslash/referencesForIndexProperty.ts | 8 +- .../fourslash/referencesForIndexProperty2.ts | 2 +- .../fourslash/referencesForIndexProperty3.ts | 4 +- .../referencesForInheritedProperties.ts | 25 +++- .../referencesForInheritedProperties2.ts | 25 +++- .../referencesForInheritedProperties3.ts | 8 +- .../referencesForInheritedProperties4.ts | 15 ++- .../referencesForInheritedProperties5.ts | 22 +++- .../referencesForInheritedProperties6.ts | 21 ++- .../referencesForInheritedProperties7.ts | 44 ++++--- .../referencesForInheritedProperties8.ts | 13 +- .../referencesForInheritedProperties9.ts | 12 +- tests/cases/fourslash/referencesForLabel.ts | 4 +- tests/cases/fourslash/referencesForLabel2.ts | 3 +- tests/cases/fourslash/referencesForLabel3.ts | 3 +- tests/cases/fourslash/referencesForLabel4.ts | 2 +- tests/cases/fourslash/referencesForLabel5.ts | 4 +- tests/cases/fourslash/referencesForLabel6.ts | 6 +- .../referencesForMergedDeclarations.ts | 13 +- .../referencesForMergedDeclarations2.ts | 4 +- .../referencesForMergedDeclarations3.ts | 12 +- .../referencesForMergedDeclarations4.ts | 10 +- .../referencesForMergedDeclarations5.ts | 14 +- .../referencesForMergedDeclarations6.ts | 4 +- .../referencesForMergedDeclarations7.ts | 14 +- .../referencesForMergedDeclarations8.ts | 4 +- .../cases/fourslash/referencesForNoContext.ts | 12 +- ...eferencesForNumericLiteralPropertyNames.ts | 19 ++- .../referencesForObjectLiteralProperties.ts | 10 +- .../cases/fourslash/referencesForOverrides.ts | 93 +++++++++++--- .../referencesForPropertiesOfGenericType.ts | 14 +- tests/cases/fourslash/referencesForStatic.ts | 4 +- ...rencesForStaticsAndMembersWithSameNames.ts | 19 +-- ...referencesForStringLiteralPropertyNames.ts | 18 ++- ...eferencesForStringLiteralPropertyNames2.ts | 11 +- ...eferencesForStringLiteralPropertyNames3.ts | 12 +- ...eferencesForStringLiteralPropertyNames4.ts | 12 +- .../fourslash/referencesForUnionProperties.ts | 22 +++- tests/cases/fourslash/referencesInComment.ts | 2 +- tests/cases/fourslash/remoteGetReferences.ts | 42 ++++-- tests/cases/fourslash/renameDefaultImport.ts | 10 +- .../renameDefaultImportDifferentName.ts | 10 +- .../renameImportAndExportInDiffFiles.ts | 8 +- .../shims-pp/getReferencesAtPosition.ts | 12 +- .../shims/getReferencesAtPosition.ts | 12 +- tests/cases/fourslash/untypedModuleImport.ts | 6 +- 166 files changed, 1349 insertions(+), 776 deletions(-) delete mode 100644 tests/cases/fourslash/findAllRefsForDefaultExport04.ts delete mode 100644 tests/cases/fourslash/findAllRefsForDefaultExport05.ts delete mode 100644 tests/cases/fourslash/findAllRefsForDefaultExport06.ts delete mode 100644 tests/cases/fourslash/findAllRefsForDefaultExport07.ts delete mode 100644 tests/cases/fourslash/findAllRefsObjectBindingElementPropertyName09.ts diff --git a/src/harness/fourslash.ts b/src/harness/fourslash.ts index 721647df0cd..3deddf1f2cc 100644 --- a/src/harness/fourslash.ts +++ b/src/harness/fourslash.ts @@ -452,7 +452,8 @@ namespace FourSlash { } private messageAtLastKnownMarker(message: string) { - return "Marker: " + this.lastKnownMarker + "\n" + message; + const locationDescription = this.lastKnownMarker ? this.lastKnownMarker : this.getLineColStringAtPosition(this.currentCaretPosition); + return `At ${locationDescription}: ${message}`; } private assertionMessageAtLastKnownMarker(msg: string) { @@ -562,7 +563,7 @@ namespace FourSlash { } public verifyGoToDefinitionIs(endMarker: string | string[]) { - this.verifyGoToXWorker(endMarker instanceof Array ? endMarker : [endMarker], () => this.getGoToDefinition()); + this.verifyGoToXWorker(toArray(endMarker), () => this.getGoToDefinition()); } public verifyGoToDefinition(arg0: any, endMarkerNames?: string | string[]) { @@ -582,7 +583,7 @@ namespace FourSlash { if (endMarkerNames) { this.verifyGoToXPlain(arg0, endMarkerNames, getDefs); } - else if (arg0 instanceof Array) { + else if (ts.isArray(arg0)) { const pairs: [string | string[], string | string[]][] = arg0; for (const [start, end] of pairs) { this.verifyGoToXPlain(start, end, getDefs); @@ -599,13 +600,8 @@ namespace FourSlash { } private verifyGoToXPlain(startMarkerNames: string | string[], endMarkerNames: string | string[], getDefs: () => ts.DefinitionInfo[] | undefined) { - if (startMarkerNames instanceof Array) { - for (const start of startMarkerNames) { - this.verifyGoToXSingle(start, endMarkerNames, getDefs); - } - } - else { - this.verifyGoToXSingle(startMarkerNames, endMarkerNames, getDefs); + for (const start of toArray(startMarkerNames)) { + this.verifyGoToXSingle(start, endMarkerNames, getDefs); } } @@ -617,7 +613,7 @@ namespace FourSlash { private verifyGoToXSingle(startMarkerName: string, endMarkerNames: string | string[], getDefs: () => ts.DefinitionInfo[] | undefined) { this.goToMarker(startMarkerName); - this.verifyGoToXWorker(endMarkerNames instanceof Array ? endMarkerNames : [endMarkerNames], getDefs); + this.verifyGoToXWorker(toArray(endMarkerNames), getDefs); } private verifyGoToXWorker(endMarkers: string[], getDefs: () => ts.DefinitionInfo[] | undefined) { @@ -899,8 +895,74 @@ namespace FourSlash { } } - public verifyRangesWithSameTextReferenceEachOther() { - this.rangesByText().forEach(ranges => this.verifyRangesReferenceEachOther(ranges)); + public verifyReferenceGroups(startRanges: Range | Range[], parts: Array<{ definition: string, ranges: Range[] }>): void { + interface ReferenceJson { definition: string; ranges: ts.ReferenceEntry[]; } + type ReferencesJson = ReferenceJson[]; + const fullExpected = parts.map(({ definition, ranges }) => ({ definition, ranges: ranges.map(rangeToReferenceEntry) })); + + for (const startRange of toArray(startRanges)) { + this.goToRangeStart(startRange); + const fullActual = this.findReferencesAtCaret().map(({ definition, references }) => ({ + definition: definition.displayParts.map(d => d.text).join(""), + ranges: references + })); + this.assertObjectsEqual(fullActual, fullExpected); + } + + function rangeToReferenceEntry(r: Range) { + let { isWriteAccess, isDefinition } = (r.marker && r.marker.data) || { isWriteAccess: false, isDefinition: false }; + isWriteAccess = isWriteAccess || false; isDefinition = isDefinition || false; + return { fileName: r.fileName, textSpan: { start: r.start, length: r.end - r.start }, isWriteAccess, isDefinition } + } + } + + public verifyNoReferences(markerNameOrRange?: string | Range) { + if (markerNameOrRange) { + if (typeof markerNameOrRange === "string") { + this.goToMarker(markerNameOrRange); + } + else { + this.goToRangeStart(markerNameOrRange); + } + } + + const refs = this.getReferencesAtCaret(); + if (refs && refs.length) { + console.log(refs); + this.raiseError("Expected getReferences to fail"); + } + } + + public verifySingleReferenceGroup(definition: string, ranges?: Range[]) { + ranges = ranges || this.getRanges(); + this.verifyReferenceGroups(ranges, [{ definition, ranges }]); + } + + private assertObjectsEqual(fullActual: T, fullExpected: T, msgPrefix = ""): void { + const recur = (actual: U, expected: U, path: string) => { + const fail = (msg: string) => { + console.log("Expected:", stringify(fullExpected)); + console.log("Actual: ", stringify(fullActual)); + this.raiseError(`${msgPrefix}At ${path}: ${msg}`); + }; + + for (const key in actual) if (ts.hasProperty(actual as any, key)) { + const ak = actual[key], ek = expected[key]; + if (typeof ak === "object" && typeof ek === "object") { + recur(ak, ek, path ? path + "." + key : key); + } + else if (ak !== ek) { + fail(`Expected '${key}' to be '${ek}', got '${ak}'`); + } + } + for (const key in expected) if (ts.hasProperty(expected as any, key)) { + if (!ts.hasProperty(actual as any, key)) { + fail(`${msgPrefix}Missing property '${key}'`); + } + } + }; + recur(fullActual, fullExpected, ""); + } public verifyDisplayPartsOfReferencedSymbol(expected: ts.SymbolDisplayPart[]) { @@ -974,7 +1036,7 @@ namespace FourSlash { public verifyQuickInfos(namesAndTexts: { [name: string]: string | [string, string] }) { for (const name in namesAndTexts) if (ts.hasProperty(namesAndTexts, name)) { const text = namesAndTexts[name]; - if (text instanceof Array) { + if (ts.isArray(text)) { assert(text.length === 2); const [expectedText, expectedDocumentation] = text; this.verifyQuickInfoAt(name, expectedText, expectedDocumentation); @@ -1411,13 +1473,6 @@ namespace FourSlash { Harness.IO.log(membersString); } - public printReferences() { - const references = this.getReferencesAtCaret(); - ts.forEach(references, entry => { - Harness.IO.log(stringify(entry)); - }); - } - public printContext() { ts.forEach(this.languageServiceAdapterHost.getFilenames(), Harness.IO.log); } @@ -3082,6 +3137,10 @@ ${code} } return ts.arrayFrom(set.keys()); } + + function toArray(x: T | T[]): T[] { + return ts.isArray(x) ? x : [x]; + } } namespace FourSlashInterface { @@ -3346,6 +3405,18 @@ namespace FourSlashInterface { this.state.verifyReferencesOf(start, references); } + public referenceGroups(startRanges: FourSlash.Range[], parts: Array<{ definition: string, ranges: FourSlash.Range[] }>) { + this.state.verifyReferenceGroups(startRanges, parts); + } + + public noReferences(markerNameOrRange?: string | FourSlash.Range) { + this.state.verifyNoReferences(markerNameOrRange); + } + + public singleReferenceGroup(definition: string, ranges?: FourSlash.Range[]) { + this.state.verifySingleReferenceGroup(definition, ranges); + } + public rangesReferenceEachOther(ranges?: FourSlash.Range[]) { this.state.verifyRangesReferenceEachOther(ranges); } @@ -3354,10 +3425,6 @@ namespace FourSlashInterface { this.state.verifyDisplayPartsOfReferencedSymbol(expected); } - public rangesWithSameTextReferenceEachOther() { - this.state.verifyRangesWithSameTextReferenceEachOther(); - } - public currentParameterHelpArgumentNameIs(name: string) { this.state.verifyCurrentParameterHelpName(name); } @@ -3660,10 +3727,6 @@ namespace FourSlashInterface { this.state.printNavigationBar(); } - public printReferences() { - this.state.printReferences(); - } - public printContext() { this.state.printContext(); } diff --git a/src/services/findAllReferences.ts b/src/services/findAllReferences.ts index 28474839cf3..cd1477c4448 100644 --- a/src/services/findAllReferences.ts +++ b/src/services/findAllReferences.ts @@ -5,6 +5,10 @@ namespace ts.FindAllReferences { return getReferencedSymbolsForNode(typeChecker, cancellationToken, node, sourceFiles, findInStrings, findInComments, isForRename); } + export function convertReferences(referenceSymbols: ReferencedSymbol[]): ReferenceEntry[] { + return referenceSymbols && flatMap(referenceSymbols, r => r.references); + } + export function getReferencedSymbolsForNode(typeChecker: TypeChecker, cancellationToken: CancellationToken, node: Node, sourceFiles: SourceFile[], findInStrings?: boolean, findInComments?: boolean, isForRename?: boolean, implementations?: boolean): ReferencedSymbol[] | undefined { if (!implementations) { const special = getReferencedSymbolsSpecial(node, sourceFiles, typeChecker, cancellationToken); @@ -411,7 +415,6 @@ namespace ts.FindAllReferences { textSpan: createTextSpan(0, 1), displayParts: [{ text: name, kind: ScriptElementKind.keyword }] } - const references: ReferenceEntry[] = []; for (const sourceFile of sourceFiles) { cancellationToken.throwIfCancellationRequested(); @@ -1316,20 +1319,6 @@ namespace ts.FindAllReferences { return meaning; } - export function convertReferences(referenceSymbols: ReferencedSymbol[]): ReferenceEntry[] { - if (!referenceSymbols) { - return undefined; - } - - const referenceEntries: ReferenceEntry[] = []; - - for (const referenceSymbol of referenceSymbols) { - addRange(referenceEntries, referenceSymbol.references); - } - - return referenceEntries; - } - function isImplementation(node: Node): boolean { if (!node) { return false; diff --git a/src/services/services.ts b/src/services/services.ts index b3e3093cddb..b83995e31ed 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -1415,7 +1415,6 @@ namespace ts { function findReferences(fileName: string, position: number): ReferencedSymbol[] { const referencedSymbols = findReferencedSymbols(fileName, position, /*findInStrings*/ false, /*findInComments*/ false, /*isForRename*/false); - // Only include referenced symbols that have a valid definition. return filter(referencedSymbols, rs => !!rs.definition); } @@ -2015,9 +2014,5 @@ namespace ts { throw new Error("getDefaultLibFilePath is only supported when consumed as a node module. "); } - function initializeServices() { - objectAllocator = getServicesObjectAllocator(); - } - - initializeServices(); + objectAllocator = getServicesObjectAllocator(); } diff --git a/tests/cases/fourslash/ambientShorthandFindAllRefs.ts b/tests/cases/fourslash/ambientShorthandFindAllRefs.ts index 2f0dbf914e7..06bc6e94782 100644 --- a/tests/cases/fourslash/ambientShorthandFindAllRefs.ts +++ b/tests/cases/fourslash/ambientShorthandFindAllRefs.ts @@ -4,9 +4,18 @@ ////declare module "jquery"; // @Filename: user.ts -////import {[|x|]} from "jquery"; +////import {[|{| "isWriteAccess": true, "isDefinition": true |}x|]} from "jquery"; // @Filename: user2.ts -////import {[|x|]} from "jquery"; +////import {[|{| "isWriteAccess": true, "isDefinition": true |}x|]} from "jquery"; -verify.rangesReferenceEachOther(); +const ranges = test.ranges(); +const [r0, r1] = ranges; +verify.referenceGroups(r0, [ + { definition: "import x", ranges: [r0] }, + { definition: 'module "jquery"', ranges: [r1] } +]); +verify.referenceGroups(r1, [ + { definition: 'module "jquery"', ranges: [r0] }, + { definition: "import x", ranges: [r1] } +]); diff --git a/tests/cases/fourslash/cancellationWhenfindingAllRefsOnDefinition.ts b/tests/cases/fourslash/cancellationWhenfindingAllRefsOnDefinition.ts index d3d18b2dabb..8f80c871eb3 100644 --- a/tests/cases/fourslash/cancellationWhenfindingAllRefsOnDefinition.ts +++ b/tests/cases/fourslash/cancellationWhenfindingAllRefsOnDefinition.ts @@ -7,7 +7,7 @@ //// //// } //// -//// public /**/[|start|](){ +//// public /**/[|{| "isWriteAccess": true, "isDefinition": true |}start|](){ //// return this; //// } //// @@ -23,11 +23,21 @@ ////second.[|start|](); ////second.stop(); -verify.rangesReferenceEachOther(); +checkRefs(); cancellation.setCancelled(); -verifyOperationIsCancelled(() => verify.rangesReferenceEachOther()); +verifyOperationIsCancelled(checkRefs); // verify that internal state is still correct cancellation.resetCancelled(); -verify.rangesReferenceEachOther(); +checkRefs(); + +function checkRefs() { + const ranges = test.ranges(); + const [r0, r1] = ranges; + verify.referenceGroups(r0, [{ definition: "(method) Test.start(): this", ranges }]); + verify.referenceGroups(r1, [ + { definition: "(method) Second.Test.start(): Second.Test", ranges: [r0] }, + { definition: "(method) Second.Test.start(): Second.Test", ranges: [r1] } + ]); +} diff --git a/tests/cases/fourslash/findAllReferencesOfConstructor.ts b/tests/cases/fourslash/findAllReferencesOfConstructor.ts index b25508a60db..dcdc23bdc7f 100644 --- a/tests/cases/fourslash/findAllReferencesOfConstructor.ts +++ b/tests/cases/fourslash/findAllReferencesOfConstructor.ts @@ -41,6 +41,6 @@ ////class d extends a.C { constructor() { [|super|](); } const ranges = test.ranges(); -for (const ctr of ranges.slice(0, 3)) { - verify.referencesOf(ctr, ranges); -} +const [r0, r1, r2] = ranges; +verify.referenceGroups([r0, r2], [{ definition: "constructor C(n: number): C (+1 overload)", ranges }]); +verify.referenceGroups(r1, [{ definition: "constructor C(): C (+1 overload)", ranges }]); diff --git a/tests/cases/fourslash/findAllReferencesOfConstructor_badOverload.ts b/tests/cases/fourslash/findAllReferencesOfConstructor_badOverload.ts index 77479bad113..bb8b62a1462 100644 --- a/tests/cases/fourslash/findAllReferencesOfConstructor_badOverload.ts +++ b/tests/cases/fourslash/findAllReferencesOfConstructor_badOverload.ts @@ -5,4 +5,4 @@ //// [|constructor|](){} ////} -verify.rangesReferenceEachOther(); +verify.singleReferenceGroup("constructor C(n: number): C"); diff --git a/tests/cases/fourslash/findAllRefsForComputedProperties.ts b/tests/cases/fourslash/findAllRefsForComputedProperties.ts index 065d34c6fc5..72c49104ded 100644 --- a/tests/cases/fourslash/findAllRefsForComputedProperties.ts +++ b/tests/cases/fourslash/findAllRefsForComputedProperties.ts @@ -1,16 +1,26 @@ /// - ////interface I { -//// ["[|prop1|]"]: () => void; +//// ["[|{| "isDefinition": true |}prop1|]"]: () => void; ////} //// ////class C implements I { -//// ["[|prop1|]"]: any; +//// ["[|{| "isDefinition": true |}prop1|]"]: any; ////} //// ////var x: I = { -//// ["[|prop1|]"]: function () { }, +//// ["[|{| "isDefinition": true |}prop1|]"]: function () { }, ////} -verify.rangesReferenceEachOther(); +const ranges = test.ranges(); +const [r0, r1, r2] = ranges; +verify.referenceGroups(r0, [{ definition: '(property) I[["prop1"]]: () => void', ranges }]); +verify.referenceGroups(r1, [ + { definition: '(property) I[["prop1"]]: () => void', ranges: [r0, r2] }, + { definition: '(property) C[["prop1"]]: any', ranges: [r1] } +]); +verify.referenceGroups(r2, [ + { definition: '(property) I[["prop1"]]: () => void', ranges: [r0, r1] }, + { definition: '(property) ["prop1"]: () => void', ranges: [r2] } +]); + diff --git a/tests/cases/fourslash/findAllRefsForComputedProperties2.ts b/tests/cases/fourslash/findAllRefsForComputedProperties2.ts index 37a9bd8470e..4a7a17047ec 100644 --- a/tests/cases/fourslash/findAllRefsForComputedProperties2.ts +++ b/tests/cases/fourslash/findAllRefsForComputedProperties2.ts @@ -1,15 +1,25 @@ /// ////interface I { -//// [[|42|]](): void; +//// [[|{| "isDefinition": true |}42|]](): void; ////} //// ////class C implements I { -//// [[|42|]]: any; +//// [[|{| "isDefinition": true |}42|]]: any; ////} //// ////var x: I = { -//// ["[|42|]"]: function () { } +//// ["[|{| "isDefinition": true |}42|]"]: function () { } ////} -verify.rangesReferenceEachOther(); +const ranges = test.ranges(); +const [r0, r1, r2] = ranges; +verify.referenceGroups(r0, [{ definition: "(method) I[[42]](): void", ranges }]); +verify.referenceGroups(r1, [ + { definition: "(method) I[[42]](): void", ranges: [r0, r2] }, + { definition: "(property) C[[42]]: any", ranges: [r1] } +]); +verify.referenceGroups(r2, [ + { definition: "(method) I[[42]](): void", ranges: [r0, r1] }, + { definition: '(property) ["42"]: () => void', ranges: [r2] } +]); diff --git a/tests/cases/fourslash/findAllRefsForDefaultExport.ts b/tests/cases/fourslash/findAllRefsForDefaultExport.ts index a27227b907a..c518bb8f59e 100644 --- a/tests/cases/fourslash/findAllRefsForDefaultExport.ts +++ b/tests/cases/fourslash/findAllRefsForDefaultExport.ts @@ -1,11 +1,11 @@ /// // @Filename: a.ts -////export default function /*def*/[|f|]() {} +////export default function /*def*/[|{| "isWriteAccess": true, "isDefinition": true |}f|]() {} // @Filename: b.ts -////import [|g|] from "./a"; +////import [|{| "isWriteAccess": true, "isDefinition": true |}g|] from "./a"; /////*ref*/[|g|](); -verify.rangesReferenceEachOther(); +verify.singleReferenceGroup("function f(): void"); verify.goToDefinition("ref", "def"); diff --git a/tests/cases/fourslash/findAllRefsForDefaultExport01.ts b/tests/cases/fourslash/findAllRefsForDefaultExport01.ts index 39079294a3b..c04550e54f3 100644 --- a/tests/cases/fourslash/findAllRefsForDefaultExport01.ts +++ b/tests/cases/fourslash/findAllRefsForDefaultExport01.ts @@ -1,10 +1,13 @@ /// -////export default class [|DefaultExportedClass|] { +////export default class [|{| "isWriteAccess": true, "isDefinition": true |}DefaultExportedClass|] { ////} //// ////var x: [|DefaultExportedClass|]; //// ////var y = new [|DefaultExportedClass|]; -verify.rangesReferenceEachOther(); +const ranges = test.ranges(); +const [r0, r1, r2] = ranges; +verify.referenceGroups([r0, r1], [{ definition: "class DefaultExportedClass", ranges }]); +verify.referenceGroups(r2, [{ definition: "constructor DefaultExportedClass(): DefaultExportedClass", ranges }]); diff --git a/tests/cases/fourslash/findAllRefsForDefaultExport02.ts b/tests/cases/fourslash/findAllRefsForDefaultExport02.ts index 19f31ece9b0..558bbd2de85 100644 --- a/tests/cases/fourslash/findAllRefsForDefaultExport02.ts +++ b/tests/cases/fourslash/findAllRefsForDefaultExport02.ts @@ -1,11 +1,22 @@ /// -////export default function [|DefaultExportedFunction|]() { -//// return [|DefaultExportedFunction|] +////export default function [|{| "isWriteAccess": true, "isDefinition": true |}DefaultExportedFunction|]() { +//// return [|DefaultExportedFunction|]; ////} //// ////var x: typeof [|DefaultExportedFunction|]; //// ////var y = [|DefaultExportedFunction|](); +//// +////namespace [|{| "isWriteAccess": true, "isDefinition": true |}DefaultExportedFunction|] { +////} -verify.rangesReferenceEachOther(); + +const ranges = test.ranges(); +const [r0, r1, r2, r3, r4] = ranges; +const fnRanges = [r0, r1, r2, r3]; +verify.singleReferenceGroup("function DefaultExportedFunction(): () => typeof DefaultExportedFunction", fnRanges); + +// The namespace and function do not merge, +// so the namespace should be all alone. +verify.singleReferenceGroup("namespace DefaultExportedFunction", [r4]); diff --git a/tests/cases/fourslash/findAllRefsForDefaultExport03.ts b/tests/cases/fourslash/findAllRefsForDefaultExport03.ts index b9bbfa14a64..d94043f4016 100644 --- a/tests/cases/fourslash/findAllRefsForDefaultExport03.ts +++ b/tests/cases/fourslash/findAllRefsForDefaultExport03.ts @@ -1,6 +1,6 @@ /// -////function [|f|]() { +////function [|{| "isWriteAccess": true, "isDefinition": true |}f|]() { //// return 100; ////} //// @@ -10,8 +10,11 @@ //// ////var y = [|f|](); //// -////namespace [|f|] { +////namespace [|{| "isWriteAccess": true, "isDefinition": true |}f|] { //// var local = 100; ////} -verify.rangesReferenceEachOther(); +const ranges = test.ranges(); +const [r0, r1, r2, r3, r4] = ranges; +verify.referenceGroups([r0, r3], [{ definition: "function f(): number\nnamespace f", ranges }]); +verify.referenceGroups([r1, r2, r4], [{ definition: "namespace f\nfunction f(): number", ranges }]); diff --git a/tests/cases/fourslash/findAllRefsForDefaultExport04.ts b/tests/cases/fourslash/findAllRefsForDefaultExport04.ts deleted file mode 100644 index 44b7ee0a06f..00000000000 --- a/tests/cases/fourslash/findAllRefsForDefaultExport04.ts +++ /dev/null @@ -1,23 +0,0 @@ -/// - -////function f() { -//// return 100; -////} -//// -////export default [|f|]; -//// -////var x: typeof f; -//// -////var y = f(); -//// -////namespace /**/[|f|] { -////} - -// The function 'f' and the namespace 'f' don't get merged, -// but the 'export default' site, includes both meanings. - -// Here we are testing whether the 'export default' -// site is included in the references to the namespace. - -goTo.marker(); -verify.referencesAre(test.ranges()); diff --git a/tests/cases/fourslash/findAllRefsForDefaultExport05.ts b/tests/cases/fourslash/findAllRefsForDefaultExport05.ts deleted file mode 100644 index 0f06792458d..00000000000 --- a/tests/cases/fourslash/findAllRefsForDefaultExport05.ts +++ /dev/null @@ -1,23 +0,0 @@ -/// - -////function /**/[|f|]() { -//// return 100; -////} -//// -////export default [|f|]; -//// -////var x: typeof [|f|]; -//// -////var y = [|f|](); -//// -////namespace f { -////} - -// The function 'f' and the namespace 'f' don't get merged, -// but the 'export default' site, includes both meanings. - -// Here we are testing whether the 'export default' site -// and all value-uses of 'f' are included in the references to the function. - -goTo.marker(); -verify.referencesAre(test.ranges()); diff --git a/tests/cases/fourslash/findAllRefsForDefaultExport06.ts b/tests/cases/fourslash/findAllRefsForDefaultExport06.ts deleted file mode 100644 index cdd9b4f980c..00000000000 --- a/tests/cases/fourslash/findAllRefsForDefaultExport06.ts +++ /dev/null @@ -1,23 +0,0 @@ -/// - -////function [|f|]() { -//// return 100; -////} -//// -////export default /**/[|f|]; -//// -////var x: typeof [|f|]; -//// -////var y = [|f|](); -//// -////namespace [|f|] { -////} - -// The function 'f' and the namespace 'f' don't get merged, -// but the 'export default' site, includes both meanings. - -// Here we are testing whether the 'export default' site -// and all value-uses of 'f' are included in the references to the function. - -goTo.marker(); -verify.referencesAre(test.ranges()); diff --git a/tests/cases/fourslash/findAllRefsForDefaultExport07.ts b/tests/cases/fourslash/findAllRefsForDefaultExport07.ts deleted file mode 100644 index 88d0a775026..00000000000 --- a/tests/cases/fourslash/findAllRefsForDefaultExport07.ts +++ /dev/null @@ -1,16 +0,0 @@ -/// - -////export default function DefaultExportedFunction() { -//// return DefaultExportedFunction -////} -//// -////var x: typeof DefaultExportedFunction; -//// -////var y = DefaultExportedFunction(); -//// -////namespace [|DefaultExportedFunction|] { -////} - -// The namespace and function do not merge, -// so the namespace should be all alone. -verify.rangesReferenceEachOther(); diff --git a/tests/cases/fourslash/findAllRefsForDefaultExport08.ts b/tests/cases/fourslash/findAllRefsForDefaultExport08.ts index b7ae7f4d534..b29060f6099 100644 --- a/tests/cases/fourslash/findAllRefsForDefaultExport08.ts +++ b/tests/cases/fourslash/findAllRefsForDefaultExport08.ts @@ -7,10 +7,9 @@ //// ////var y = new DefaultExportedClass; //// -////namespace [|DefaultExportedClass|] { +////namespace [|{| "isWriteAccess": true, "isDefinition": true |}DefaultExportedClass|] { ////} // The namespace and class do not merge, // so the namespace should be all alone. - -verify.rangesReferenceEachOther(); +verify.singleReferenceGroup("namespace DefaultExportedClass"); diff --git a/tests/cases/fourslash/findAllRefsForFunctionExpression01.ts b/tests/cases/fourslash/findAllRefsForFunctionExpression01.ts index 35d5c45e3d9..15ff0aca5cb 100644 --- a/tests/cases/fourslash/findAllRefsForFunctionExpression01.ts +++ b/tests/cases/fourslash/findAllRefsForFunctionExpression01.ts @@ -1,7 +1,7 @@ /// // @Filename: file1.ts -////var foo = function [|foo|](a = [|foo|](), b = () => [|foo|]) { +////var foo = function [|{| "isWriteAccess": true, "isDefinition": true |}foo|](a = [|foo|](), b = () => [|foo|]) { //// [|foo|]([|foo|], [|foo|]); ////} @@ -9,4 +9,4 @@ /////// ////foo(); -verify.rangesReferenceEachOther(); +verify.singleReferenceGroup("(local function) foo(a?: void, b?: () => (a?: void, b?: any) => void): void"); diff --git a/tests/cases/fourslash/findAllRefsForMappedType.ts b/tests/cases/fourslash/findAllRefsForMappedType.ts index 38fb3a226c6..a841c7e6e46 100644 --- a/tests/cases/fourslash/findAllRefsForMappedType.ts +++ b/tests/cases/fourslash/findAllRefsForMappedType.ts @@ -1,9 +1,19 @@ /// -////interface T { [|a|]: number }; +////interface T { [|{| "isWriteAccess": true, "isDefinition": true |}a|]: number }; ////type U = { [K in keyof T]: string }; ////type V = { [K in keyof U]: boolean }; -////const u: U = { [|a|]: "" } -////const v: V = { [|a|]: true } +////const u: U = { [|{| "isWriteAccess": true, "isDefinition": true |}a|]: "" } +////const v: V = { [|{| "isWriteAccess": true, "isDefinition": true |}a|]: true } -verify.rangesReferenceEachOther(); +const ranges = test.ranges(); +const [r0, r1, r2] = ranges; +verify.referenceGroups(r0, [{ definition: "(property) T.a: number", ranges }]); +verify.referenceGroups(r1, [ + { definition: "(property) T.a: number", ranges: [r0, r2] }, + { definition: "(property) a: string", ranges: [r1] } +]); +verify.referenceGroups(r2, [ + { definition: "(property) T.a: number", ranges: [r0, r1] }, + { definition: "(property) a: boolean", ranges: [r2] } +]); diff --git a/tests/cases/fourslash/findAllRefsForObjectLiteralProperties.ts b/tests/cases/fourslash/findAllRefsForObjectLiteralProperties.ts index cea4db81ea1..125a11f19c4 100644 --- a/tests/cases/fourslash/findAllRefsForObjectLiteralProperties.ts +++ b/tests/cases/fourslash/findAllRefsForObjectLiteralProperties.ts @@ -1,11 +1,17 @@ /// ////var x = { -//// [|property|]: {} +//// [|{| "isWriteAccess": true, "isDefinition": true |}property|]: {} ////}; //// ////x.[|property|]; //// ////let {[|property|]: pVar} = x; -verify.rangesReferenceEachOther(); +const ranges = test.ranges(); +const [r0, r1, r2] = ranges; +verify.referenceGroups(r0, [{ definition: "(property) property: {}", ranges }]); +verify.referenceGroups([r1, r2], [ + { definition: "(property) property: {}", ranges: [r0] }, + { definition: "(property) property: {}", ranges: [r1, r2] } +]); diff --git a/tests/cases/fourslash/findAllRefsForObjectSpread.ts b/tests/cases/fourslash/findAllRefsForObjectSpread.ts index 05c83491f66..a65f18ef57c 100644 --- a/tests/cases/fourslash/findAllRefsForObjectSpread.ts +++ b/tests/cases/fourslash/findAllRefsForObjectSpread.ts @@ -1,14 +1,21 @@ /// -////interface A1 { [|a|]: string }; -////interface A2 { [|a|]?: number }; +////interface A1 { [|{| "isWriteAccess": true, "isDefinition": true |}a|]: string }; +////interface A2 { [|{| "isWriteAccess": true, "isDefinition": true |}a|]?: number }; ////let a1: A1; ////let a2: A2; ////let a12 = { ...a1, ...a2 }; ////a12.[|a|]; const ranges = test.ranges(); +const [r0, r1, r2] = ranges; + // members of spread types only refer to themselves and the resulting property -verify.referencesOf(ranges[0], [ranges[0], ranges[2]]); -verify.referencesOf(ranges[1], [ranges[1], ranges[2]]); +verify.referenceGroups(r0, [{ definition: "(property) A1.a: string", ranges: [r0, r2] }]); +verify.referenceGroups(r1, [{ definition: "(property) A2.a: number", ranges: [r1, r2] }]); + // but the resulting property refers to everything -verify.referencesOf(ranges[2], ranges); +verify.referenceGroups(r2, [ + { definition: "(property) A1.a: string", ranges: [r0] }, + { definition: "(property) A2.a: number", ranges: [r1] }, + { definition: "(property) a: string | number", ranges: [r2] } +]); diff --git a/tests/cases/fourslash/findAllRefsForRest.ts b/tests/cases/fourslash/findAllRefsForRest.ts index 65d6a3c60e3..026451d68b8 100644 --- a/tests/cases/fourslash/findAllRefsForRest.ts +++ b/tests/cases/fourslash/findAllRefsForRest.ts @@ -1,11 +1,11 @@ /// ////interface Gen { //// x: number -//// [|parent|]: Gen; +//// [|{| "isWriteAccess": true, "isDefinition": true |}parent|]: Gen; //// millenial: string; ////} ////let t: Gen; ////var { x, ...rest } = t; ////rest.[|parent|]; -verify.rangesReferenceEachOther(); +verify.singleReferenceGroup("(property) Gen.parent: Gen"); diff --git a/tests/cases/fourslash/findAllRefsForStringLiteralTypes.ts b/tests/cases/fourslash/findAllRefsForStringLiteralTypes.ts index 45e981d8a84..e450102c127 100644 --- a/tests/cases/fourslash/findAllRefsForStringLiteralTypes.ts +++ b/tests/cases/fourslash/findAllRefsForStringLiteralTypes.ts @@ -3,4 +3,4 @@ ////type Options = "[|option 1|]" | "option 2"; ////let myOption: Options = "[|option 1|]"; -verify.rangesReferenceEachOther(); +verify.singleReferenceGroup('"option 1"'); diff --git a/tests/cases/fourslash/findAllRefsForUMDModuleAlias1.ts b/tests/cases/fourslash/findAllRefsForUMDModuleAlias1.ts index 4177e154532..99ca347eac4 100644 --- a/tests/cases/fourslash/findAllRefsForUMDModuleAlias1.ts +++ b/tests/cases/fourslash/findAllRefsForUMDModuleAlias1.ts @@ -4,10 +4,10 @@ //// export function doThing(): string; //// export function doTheOtherThing(): void; -//// export as namespace [|myLib|]; +//// export as namespace [|{| "isWriteAccess": true, "isDefinition": true |}myLib|]; // @Filename: 1.ts //// /// //// [|myLib|].doThing(); -verify.rangesReferenceEachOther(); +verify.singleReferenceGroup("export namespace myLib"); diff --git a/tests/cases/fourslash/findAllRefsForVariableInExtendsClause01.ts b/tests/cases/fourslash/findAllRefsForVariableInExtendsClause01.ts index dd8fb1026c4..d40cb009f1e 100644 --- a/tests/cases/fourslash/findAllRefsForVariableInExtendsClause01.ts +++ b/tests/cases/fourslash/findAllRefsForVariableInExtendsClause01.ts @@ -1,6 +1,6 @@ /// -////var [|Base|] = class { }; +////var [|{| "isWriteAccess": true, "isDefinition": true |}Base|] = class { }; ////class C extends [|Base|] { } -verify.rangesReferenceEachOther(); +verify.singleReferenceGroup("var Base: typeof (Anonymous class)"); diff --git a/tests/cases/fourslash/findAllRefsForVariableInExtendsClause02.ts b/tests/cases/fourslash/findAllRefsForVariableInExtendsClause02.ts index 3fc41358dfd..5685df0c4e1 100644 --- a/tests/cases/fourslash/findAllRefsForVariableInExtendsClause02.ts +++ b/tests/cases/fourslash/findAllRefsForVariableInExtendsClause02.ts @@ -1,9 +1,9 @@ /// -////interface [|Base|] { } +////interface [|{| "isWriteAccess": true, "isDefinition": true |}Base|] { } ////namespace n { //// var Base = class { }; //// interface I extends [|Base|] { } ////} -verify.rangesReferenceEachOther(); +verify.singleReferenceGroup("interface Base"); diff --git a/tests/cases/fourslash/findAllRefsForVariableInImplementsClause01.ts b/tests/cases/fourslash/findAllRefsForVariableInImplementsClause01.ts index f8326eade58..419b828d0b3 100644 --- a/tests/cases/fourslash/findAllRefsForVariableInImplementsClause01.ts +++ b/tests/cases/fourslash/findAllRefsForVariableInImplementsClause01.ts @@ -3,5 +3,4 @@ ////var Base = class { }; ////class C extends Base implements /**/Base { } -goTo.marker(); -verify.referencesAre([]); +verify.noReferences(""); diff --git a/tests/cases/fourslash/findAllRefsInClassExpression.ts b/tests/cases/fourslash/findAllRefsInClassExpression.ts index f874bcbcb5c..b83d8992b4f 100644 --- a/tests/cases/fourslash/findAllRefsInClassExpression.ts +++ b/tests/cases/fourslash/findAllRefsInClassExpression.ts @@ -1,8 +1,14 @@ /// -////interface I { [|boom|](): void; } +////interface I { [|{| "isWriteAccess": true, "isDefinition": true |}boom|](): void; } ////new class C implements I { -//// [|boom|](){} +//// [|{| "isWriteAccess": true, "isDefinition": true |}boom|](){} ////} -verify.rangesReferenceEachOther(); +const ranges = test.ranges(); +const [r0, r1] = ranges; +verify.referenceGroups(r0, [{ definition: "(method) I.boom(): void", ranges }]); +verify.referenceGroups(r1, [ + { definition: "(method) I.boom(): void", ranges: [r0] }, + { definition: "(method) C.boom(): void", ranges: [r1] } +]); diff --git a/tests/cases/fourslash/findAllRefsInheritedProperties1.ts b/tests/cases/fourslash/findAllRefsInheritedProperties1.ts index 358ba3f249d..41acc117f9e 100644 --- a/tests/cases/fourslash/findAllRefsInheritedProperties1.ts +++ b/tests/cases/fourslash/findAllRefsInheritedProperties1.ts @@ -1,8 +1,8 @@ /// //// class class1 extends class1 { -//// [|doStuff|]() { } -//// [|propName|]: string; +//// [|{| "isWriteAccess": true, "isDefinition": true |}doStuff|]() { } +//// [|{| "isWriteAccess": true, "isDefinition": true |}propName|]: string; //// } //// //// var v: class1; @@ -10,7 +10,9 @@ //// v.[|propName|]; const [r0, r1, r2, r3] = test.ranges(); -verify.referencesOf(r0, [r0, r2]); -verify.referencesOf(r1, [r1, r3]); -verify.referencesOf(r2, [r0, r2]); -verify.referencesOf(r3, [r1, r3]); +verify.referenceGroups(r0, [{ definition: "(method) class1.doStuff(): void", ranges: [r0, r2] }]); +verify.referenceGroups(r2, [ + { definition: "(method) class1.doStuff(): void", ranges: [r0] }, + { definition: "(method) class1.doStuff(): void", ranges: [r2] } +]); +verify.singleReferenceGroup("(property) class1.propName: string", [r1, r3]); diff --git a/tests/cases/fourslash/findAllRefsInheritedProperties2.ts b/tests/cases/fourslash/findAllRefsInheritedProperties2.ts index 9fe36fbb48e..23badd64d48 100644 --- a/tests/cases/fourslash/findAllRefsInheritedProperties2.ts +++ b/tests/cases/fourslash/findAllRefsInheritedProperties2.ts @@ -1,8 +1,8 @@ /// //// interface interface1 extends interface1 { -//// [|doStuff|](): void; // r0 -//// [|propName|]: string; // r1 +//// [|{| "isWriteAccess": true, "isDefinition": true |}doStuff|](): void; // r0 +//// [|{| "isWriteAccess": true, "isDefinition": true |}propName|]: string; // r1 //// } //// //// var v: interface1; @@ -10,7 +10,5 @@ //// v.[|propName|]; // r3 const [r0, r1, r2, r3] = test.ranges(); -verify.referencesOf(r0, [r0, r2]); -verify.referencesOf(r1, [r1, r3]); -verify.referencesOf(r2, [r0, r2]); -verify.referencesOf(r3, [r1, r3]); +verify.singleReferenceGroup("(method) interface1.doStuff(): void", [r0, r2]); +verify.singleReferenceGroup("(property) interface1.propName: string", [r1, r3]); diff --git a/tests/cases/fourslash/findAllRefsInheritedProperties3.ts b/tests/cases/fourslash/findAllRefsInheritedProperties3.ts index 772fb78a2e8..cc82e4a4e44 100644 --- a/tests/cases/fourslash/findAllRefsInheritedProperties3.ts +++ b/tests/cases/fourslash/findAllRefsInheritedProperties3.ts @@ -1,28 +1,40 @@ /// //// class class1 extends class1 { -//// [|doStuff|]() { } // r0 -//// [|propName|]: string; // r1 +//// [|{| "isWriteAccess": true, "isDefinition": true |}doStuff|]() { } // r0 +//// [|{| "isWriteAccess": true, "isDefinition": true |}propName|]: string; // r1 //// } //// interface interface1 extends interface1 { -//// [|doStuff|](): void; // r2 -//// [|propName|]: string; // r3 +//// [|{| "isWriteAccess": true, "isDefinition": true |}doStuff|](): void; // r2 +//// [|{| "isWriteAccess": true, "isDefinition": true |}propName|]: string; // r3 //// } //// class class2 extends class1 implements interface1 { -//// [|doStuff|]() { } // r4 -//// [|propName|]: string; // r5 +//// [|{| "isWriteAccess": true, "isDefinition": true |}doStuff|]() { } // r4 +//// [|{| "isWriteAccess": true, "isDefinition": true |}propName|]: string; // r5 //// } -//// +//// //// var v: class2; -//// v.[|propName|]; // r6 -//// v.[|doStuff|](); // r7 +//// v.[|doStuff|](); // r6 +//// v.[|propName|]; // r7 const [r0, r1, r2, r3, r4, r5, r6, r7] = test.ranges(); -verify.referencesOf(r0, [r0, r4, r7]); -verify.referencesOf(r1, [r1, r5, r6]); -verify.referencesOf(r2, [r2, r4, r7]); -verify.referencesOf(r3, [r3, r5, r6]); -verify.referencesOf(r4, [r0, r2, r4, r7]); -verify.referencesOf(r5, [r1, r3, r5, r6]); -verify.referencesOf(r6, [r1, r3, r5, r6]); -verify.referencesOf(r7, [r0, r2, r4, r7]); +verify.referenceGroups(r0, [{ definition: "(method) class1.doStuff(): void", ranges: [r0, r4, r6] }]); +verify.referenceGroups(r1, [{ definition: "(property) class1.propName: string", ranges: [r1, r5, r7] }]); +verify.referenceGroups(r2, [{ definition: "(method) interface1.doStuff(): void", ranges: [r2, r4, r6] }]); +verify.referenceGroups(r3, [{ definition: "(property) interface1.propName: string", ranges: [r3, r5, r7] }]); +verify.referenceGroups(r4, [ + { definition: "(method) class1.doStuff(): void", ranges: [r0] }, + { definition: "(method) interface1.doStuff(): void", ranges: [r2] }, + { definition: "(method) class2.doStuff(): void", ranges: [r4, r6] } +]); +verify.referenceGroups([r5, r7], [ + { definition: "(property) class1.propName: string", ranges: [r1] }, + { definition: "(property) interface1.propName: string", ranges: [r3] }, + { definition: "(property) class2.propName: string", ranges: [r5, r7] } +]); +verify.referenceGroups(r6, [ + { definition: "(method) class1.doStuff(): void", ranges: [r0] }, + { definition: "(method) interface1.doStuff(): void", ranges: [r2] }, + { definition: "(method) class2.doStuff(): void", ranges: [r4] }, + { definition: "(method) class2.doStuff(): void", ranges: [r6] } +]); diff --git a/tests/cases/fourslash/findAllRefsInheritedProperties4.ts b/tests/cases/fourslash/findAllRefsInheritedProperties4.ts index 1ecb85bfae1..e2d8887bbe8 100644 --- a/tests/cases/fourslash/findAllRefsInheritedProperties4.ts +++ b/tests/cases/fourslash/findAllRefsInheritedProperties4.ts @@ -1,12 +1,12 @@ /// //// interface C extends D { -//// [|prop0|]: string; // r0 -//// [|prop1|]: number; // r1 +//// [|{| "isWriteAccess": true, "isDefinition": true |}prop0|]: string; // r0 +//// [|{| "isWriteAccess": true, "isDefinition": true |}prop1|]: number; // r1 //// } //// //// interface D extends C { -//// [|prop0|]: string; // r2 +//// [|{| "isWriteAccess": true, "isDefinition": true |}prop0|]: string; // r2 //// } //// //// var d: D; @@ -14,8 +14,9 @@ //// d.[|prop1|]; // r4 const [r0, r1, r2, r3, r4] = test.ranges(); -verify.referencesOf(r0, [r0, r2, r3]); -verify.referencesOf(r1, [r1]); -verify.referencesOf(r2, [r0, r2, r3]); -verify.referencesOf(r3, [r0, r2, r3]); -verify.referencesOf(r4, []); +verify.referenceGroups([r0, r2, r3], [ + { definition: "(property) C.prop0: string", ranges: [r0] }, + { definition: "(property) D.prop0: string", ranges: [r2, r3] } +]); +verify.singleReferenceGroup("(property) C.prop1: number", [r1]); +verify.noReferences(r4); diff --git a/tests/cases/fourslash/findAllRefsInheritedProperties5.ts b/tests/cases/fourslash/findAllRefsInheritedProperties5.ts index 6d6dbb392bf..c534a9d6aab 100644 --- a/tests/cases/fourslash/findAllRefsInheritedProperties5.ts +++ b/tests/cases/fourslash/findAllRefsInheritedProperties5.ts @@ -1,12 +1,12 @@ /// //// class C extends D { -//// [|prop0|]: string; // r0 -//// [|prop1|]: number; // r1 +//// [|{| "isWriteAccess": true, "isDefinition": true |}prop0|]: string; // r0 +//// [|{| "isWriteAccess": true, "isDefinition": true |}prop1|]: number; // r1 //// } //// //// class D extends C { -//// [|prop0|]: string; // r2 +//// [|{| "isWriteAccess": true, "isDefinition": true |}prop0|]: string; // r2 //// } //// //// var d: D; @@ -14,8 +14,7 @@ //// d.[|prop1|]; // r4 const [r0, r1, r2, r3, r4] = test.ranges(); -verify.referencesOf(r0, [r0]); -verify.referencesOf(r1, [r1]); -verify.referencesOf(r2, [r2, r3]); -verify.referencesOf(r3, [r2, r3]); -verify.referencesOf(r4, []); +verify.singleReferenceGroup("(property) C.prop0: string", [r0]); +verify.singleReferenceGroup("(property) C.prop1: number", [r1]); +verify.singleReferenceGroup("(property) D.prop0: string", [r2, r3]); +verify.noReferences(r4); diff --git a/tests/cases/fourslash/findAllRefsInsideTemplates1.ts b/tests/cases/fourslash/findAllRefsInsideTemplates1.ts index 9ab4c624230..8d41961c6fd 100644 --- a/tests/cases/fourslash/findAllRefsInsideTemplates1.ts +++ b/tests/cases/fourslash/findAllRefsInsideTemplates1.ts @@ -1,6 +1,6 @@ /// -////var [|x|] = 10; +////var [|{| "isWriteAccess": true, "isDefinition": true |}x|] = 10; ////var y = `${ [|x|] } ${ [|x|] }` -verify.rangesReferenceEachOther(); +verify.singleReferenceGroup("var x: number"); diff --git a/tests/cases/fourslash/findAllRefsInsideTemplates2.ts b/tests/cases/fourslash/findAllRefsInsideTemplates2.ts index 63265eb944b..24a4a7c131b 100644 --- a/tests/cases/fourslash/findAllRefsInsideTemplates2.ts +++ b/tests/cases/fourslash/findAllRefsInsideTemplates2.ts @@ -1,6 +1,6 @@ /// -////function [|f|](...rest: any[]) { } +////function [|{| "isWriteAccess": true, "isDefinition": true |}f|](...rest: any[]) { } ////[|f|] `${ [|f|] } ${ [|f|] }` -verify.rangesReferenceEachOther(); +verify.singleReferenceGroup("function f(...rest: any[]): void"); diff --git a/tests/cases/fourslash/findAllRefsInsideWithBlock.ts b/tests/cases/fourslash/findAllRefsInsideWithBlock.ts index c95925ff863..52936248095 100644 --- a/tests/cases/fourslash/findAllRefsInsideWithBlock.ts +++ b/tests/cases/fourslash/findAllRefsInsideWithBlock.ts @@ -1,12 +1,12 @@ /// -////var [|x|] = 0; +////var [|{| "isWriteAccess": true, "isDefinition": true |}x|] = 0; //// ////with ({}) { //// var y = x; // Reference of x here should not be picked //// /*2*/y++; // also reference for y should be ignored ////} //// -////[|x|] = [|x|] + 1; +////[|{| "isWriteAccess": true |}x|] = [|x|] + 1; -verify.rangesReferenceEachOther(); +verify.singleReferenceGroup("var x: number"); diff --git a/tests/cases/fourslash/findAllRefsObjectBindingElementPropertyName01.ts b/tests/cases/fourslash/findAllRefsObjectBindingElementPropertyName01.ts index 895b2168b23..d11bcee506f 100644 --- a/tests/cases/fourslash/findAllRefsObjectBindingElementPropertyName01.ts +++ b/tests/cases/fourslash/findAllRefsObjectBindingElementPropertyName01.ts @@ -1,11 +1,11 @@ /// ////interface I { -//// [|property1|]: number; +//// [|{| "isWriteAccess": true, "isDefinition": true |}property1|]: number; //// property2: string; ////} //// ////var foo: I; ////var { [|property1|]: prop1 } = foo; -verify.rangesReferenceEachOther(); +verify.singleReferenceGroup("(property) I.property1: number"); diff --git a/tests/cases/fourslash/findAllRefsObjectBindingElementPropertyName02.ts b/tests/cases/fourslash/findAllRefsObjectBindingElementPropertyName02.ts index 67a31f33d1e..6ad98df9cd8 100644 --- a/tests/cases/fourslash/findAllRefsObjectBindingElementPropertyName02.ts +++ b/tests/cases/fourslash/findAllRefsObjectBindingElementPropertyName02.ts @@ -1,11 +1,11 @@ /// ////interface I { -//// [|property1|]: number; +//// [|{| "isWriteAccess": true, "isDefinition": true |}property1|]: number; //// property2: string; ////} //// ////var foo: I; ////var { [|property1|]: {} } = foo; -verify.rangesReferenceEachOther(); +verify.singleReferenceGroup("(property) I.property1: number"); diff --git a/tests/cases/fourslash/findAllRefsObjectBindingElementPropertyName03.ts b/tests/cases/fourslash/findAllRefsObjectBindingElementPropertyName03.ts index 40ecf0139a7..520dbc8e1e4 100644 --- a/tests/cases/fourslash/findAllRefsObjectBindingElementPropertyName03.ts +++ b/tests/cases/fourslash/findAllRefsObjectBindingElementPropertyName03.ts @@ -1,11 +1,17 @@ /// ////interface I { -//// [|property1|]: number; +//// [|{| "isWriteAccess": true, "isDefinition": true |}property1|]: number; //// property2: string; ////} //// ////var foo: I; -////var [{ [|property1|]: prop1 }, { [|property1|], property2 } ] = [foo, foo]; +////var [{ [|property1|]: prop1 }, { [|{| "isWriteAccess": true, "isDefinition": true |}property1|], property2 } ] = [foo, foo]; -verify.rangesReferenceEachOther(); +const ranges = test.ranges(); +const [r0, r1, r2] = ranges; +verify.referenceGroups([r0, r1], [{ definition: "(property) I.property1: number", ranges }]); +verify.referenceGroups(r2, [ + { definition: "(property) I.property1: number", ranges: [r0, r1] }, + { definition: "var property1: number", ranges: [r2] } +]); diff --git a/tests/cases/fourslash/findAllRefsObjectBindingElementPropertyName04.ts b/tests/cases/fourslash/findAllRefsObjectBindingElementPropertyName04.ts index 5696d242fed..f25fff9da23 100644 --- a/tests/cases/fourslash/findAllRefsObjectBindingElementPropertyName04.ts +++ b/tests/cases/fourslash/findAllRefsObjectBindingElementPropertyName04.ts @@ -1,15 +1,22 @@ /// ////interface I { -//// [|property1|]: number; +//// [|{| "isWriteAccess": true, "isDefinition": true |}property1|]: number; //// property2: string; ////} //// ////function f({ [|property1|]: p1 }: I, -//// { [|property1|] }: I, +//// { [|{| "isWriteAccess": true, "isDefinition": true |}property1|] }: I, //// { property1: p2 }) { //// //// return [|property1|] + 1; ////} -verify.rangesReferenceEachOther(); +const ranges = test.ranges(); +const [r0, r1, r2, r3] = ranges; +verify.referenceGroups([r0, r1], [{ definition: "(property) I.property1: number", ranges }]); +verify.referenceGroups([r2, r3], [ + { definition: "(property) I.property1: number", ranges: [r0, r1] }, + { definition: "var property1: number", ranges: [r2, r3] } +]); + diff --git a/tests/cases/fourslash/findAllRefsObjectBindingElementPropertyName05.ts b/tests/cases/fourslash/findAllRefsObjectBindingElementPropertyName05.ts index e33c73ff838..f4e7bd70f7a 100644 --- a/tests/cases/fourslash/findAllRefsObjectBindingElementPropertyName05.ts +++ b/tests/cases/fourslash/findAllRefsObjectBindingElementPropertyName05.ts @@ -10,4 +10,4 @@ ////} goTo.marker(); -verify.referencesAre([]); \ No newline at end of file +verify.noReferences(""); \ No newline at end of file diff --git a/tests/cases/fourslash/findAllRefsObjectBindingElementPropertyName06.ts b/tests/cases/fourslash/findAllRefsObjectBindingElementPropertyName06.ts index 8be45ac87e6..c589dccacbc 100644 --- a/tests/cases/fourslash/findAllRefsObjectBindingElementPropertyName06.ts +++ b/tests/cases/fourslash/findAllRefsObjectBindingElementPropertyName06.ts @@ -1,22 +1,29 @@ /// ////interface I { -//// [|property1|]: number; +//// [|{| "isWriteAccess": true, "isDefinition": true |}property1|]: number; //// property2: string; ////} //// ////var elems: I[]; ////for (let { [|property1|]: p } of elems) { ////} -////for (let { [|property1|] } of elems) { +////for (let { [|{| "isWriteAccess": true, "isDefinition": true |}property1|] } of elems) { ////} ////for (var { [|property1|]: p1 } of elems) { ////} ////var p2; -////for ({ [|property1|] : p2 } of elems) { +////for ({ [|{| "isWriteAccess": true, "isDefinition": true |}property1|] : p2 } of elems) { ////} -// Note: if this test ever changes, consider updating -// 'quickInfoForObjectBindingElementPropertyName05.ts' - -verify.rangesReferenceEachOther(); +const ranges = test.ranges(); +const [r0, r1, r2, r3, r4] = ranges; +verify.referenceGroups([r0, r1, r3], [{ definition: "(property) I.property1: number", ranges }]); +verify.referenceGroups(r2, [ + { definition: "(property) I.property1: number", ranges: [r0, r1, r3, r4] }, + { definition: "let property1: number", ranges: [r2] } +]); +verify.referenceGroups(r4, [ + { definition: "(property) I.property1: number", ranges: [r0, r1, r2, r3] }, + { definition: "(property) property1: I", ranges: [r4] } +]); diff --git a/tests/cases/fourslash/findAllRefsObjectBindingElementPropertyName07.ts b/tests/cases/fourslash/findAllRefsObjectBindingElementPropertyName07.ts index 96f414dc060..f9415ab6a81 100644 --- a/tests/cases/fourslash/findAllRefsObjectBindingElementPropertyName07.ts +++ b/tests/cases/fourslash/findAllRefsObjectBindingElementPropertyName07.ts @@ -2,6 +2,12 @@ ////let p, b; //// -////p, [{ [|a|]: p, b }] = [{ [|a|]: 10, b: true }]; +////p, [{ [|{| "isWriteAccess": true, "isDefinition": true |}a|]: p, b }] = [{ [|{| "isWriteAccess": true, "isDefinition": true |}a|]: 10, b: true }]; -verify.rangesReferenceEachOther(); +const ranges = test.ranges(); +const [r0, r1] = ranges; +verify.referenceGroups(r0, [{ definition: "(property) a: any", ranges }]); +verify.referenceGroups(r1, [ + { definition: "(property) a: any", ranges: [r0] }, + { definition: "(property) a: number", ranges: [r1] } +]); diff --git a/tests/cases/fourslash/findAllRefsObjectBindingElementPropertyName09.ts b/tests/cases/fourslash/findAllRefsObjectBindingElementPropertyName09.ts deleted file mode 100644 index 5696d242fed..00000000000 --- a/tests/cases/fourslash/findAllRefsObjectBindingElementPropertyName09.ts +++ /dev/null @@ -1,15 +0,0 @@ -/// - -////interface I { -//// [|property1|]: number; -//// property2: string; -////} -//// -////function f({ [|property1|]: p1 }: I, -//// { [|property1|] }: I, -//// { property1: p2 }) { -//// -//// return [|property1|] + 1; -////} - -verify.rangesReferenceEachOther(); diff --git a/tests/cases/fourslash/findAllRefsObjectBindingElementPropertyName10.ts b/tests/cases/fourslash/findAllRefsObjectBindingElementPropertyName10.ts index 6ffa4b03b68..1c79d326dbc 100644 --- a/tests/cases/fourslash/findAllRefsObjectBindingElementPropertyName10.ts +++ b/tests/cases/fourslash/findAllRefsObjectBindingElementPropertyName10.ts @@ -1,11 +1,11 @@ /// ////interface Recursive { -//// [|next|]?: Recursive; +//// [|{| "isWriteAccess": true, "isDefinition": true |}next|]?: Recursive; //// value: any; ////} //// ////function f ({ [|next|]: { [|next|]: x} }: Recursive) { ////} -verify.rangesReferenceEachOther(); +verify.singleReferenceGroup("(property) Recursive.next: Recursive"); diff --git a/tests/cases/fourslash/findAllRefsOfConstructor_withModifier.ts b/tests/cases/fourslash/findAllRefsOfConstructor_withModifier.ts index 0954945a546..061903e703d 100644 --- a/tests/cases/fourslash/findAllRefsOfConstructor_withModifier.ts +++ b/tests/cases/fourslash/findAllRefsOfConstructor_withModifier.ts @@ -6,5 +6,4 @@ ////var x = new [|X|](); const ranges = test.ranges(); -const ctr = ranges[0]; -verify.referencesOf(ctr, ranges); +verify.referenceGroups(ranges[0], [{ definition: "constructor X(): X", ranges }]); diff --git a/tests/cases/fourslash/findAllRefsOnDecorators.ts b/tests/cases/fourslash/findAllRefsOnDecorators.ts index b58e15b9571..95bf1072014 100644 --- a/tests/cases/fourslash/findAllRefsOnDecorators.ts +++ b/tests/cases/fourslash/findAllRefsOnDecorators.ts @@ -1,7 +1,7 @@ /// // @Filename: a.ts -////function [|decorator|](target) { +////function [|{| "isWriteAccess": true, "isDefinition": true |}decorator|](target) { //// return target; ////} ////[|decorator|](); @@ -13,4 +13,4 @@ //// method() {} ////} -verify.rangesReferenceEachOther(); +verify.singleReferenceGroup("function decorator(target: any): any"); diff --git a/tests/cases/fourslash/findAllRefsOnDefinition.ts b/tests/cases/fourslash/findAllRefsOnDefinition.ts index cb829807602..7d136efc42a 100644 --- a/tests/cases/fourslash/findAllRefsOnDefinition.ts +++ b/tests/cases/fourslash/findAllRefsOnDefinition.ts @@ -7,7 +7,7 @@ //// //// } //// -//// public [|start|](){ +//// public [|{| "isWriteAccess": true, "isDefinition": true |}start|](){ //// return this; //// } //// @@ -23,4 +23,10 @@ ////second.[|start|](); ////second.stop(); -verify.rangesReferenceEachOther(); +const ranges = test.ranges(); +const [r0, r1] = ranges; +verify.referenceGroups(r0, [{ definition: "(method) Test.start(): this", ranges }]); +verify.referenceGroups(r1, [ + { definition: "(method) Second.Test.start(): Second.Test", ranges: [r0] }, + { definition: "(method) Second.Test.start(): Second.Test", ranges: [r1] }, +]); diff --git a/tests/cases/fourslash/findAllRefsOnDefinition2.ts b/tests/cases/fourslash/findAllRefsOnDefinition2.ts index 8edfd7f8cd7..6d2438a124c 100644 --- a/tests/cases/fourslash/findAllRefsOnDefinition2.ts +++ b/tests/cases/fourslash/findAllRefsOnDefinition2.ts @@ -3,7 +3,7 @@ //@Filename: findAllRefsOnDefinition2-import.ts ////export module Test{ //// -//// export interface [|start|] { } +//// export interface [|{| "isWriteAccess": true, "isDefinition": true |}start|] { } //// //// export interface stop { } ////} @@ -14,4 +14,8 @@ ////var start: Second.Test.[|start|]; ////var stop: Second.Test.stop; -verify.rangesReferenceEachOther(); +const ranges = test.ranges(); +const [r0, r1] = ranges; +verify.referenceGroups(r0, [{ definition: "interface Test.start", ranges }]); +verify.referenceGroups(r1, [{ definition: "interface Second.Test.start", ranges }]); + diff --git a/tests/cases/fourslash/findAllRefsOnImportAliases.ts b/tests/cases/fourslash/findAllRefsOnImportAliases.ts index cd258e80316..7574e11625f 100644 --- a/tests/cases/fourslash/findAllRefsOnImportAliases.ts +++ b/tests/cases/fourslash/findAllRefsOnImportAliases.ts @@ -1,15 +1,18 @@ /// //@Filename: a.ts -////export class [|Class|] { +////export class [|{| "isWriteAccess": true, "isDefinition": true |}Class|] { ////} //@Filename: b.ts -////import { [|Class|] } from "./a"; +////import { [|{| "isWriteAccess": true, "isDefinition": true |}Class|] } from "./a"; //// ////var c = new [|Class|](); //@Filename: c.ts -////export { [|Class|] } from "./a"; +////export { [|{| "isWriteAccess": true, "isDefinition": true |}Class|] } from "./a"; -verify.rangesReferenceEachOther(); +const ranges = test.ranges(); +const [r0, r1, r2, r3] = ranges; +verify.referenceGroups([r0, r1, r3], [{ definition: "class Class", ranges }]); +verify.referenceGroups(r2, [{ definition: "constructor Class(): Class", ranges }]); diff --git a/tests/cases/fourslash/findAllRefsOnImportAliases2.ts b/tests/cases/fourslash/findAllRefsOnImportAliases2.ts index 67c4d14b5d9..a21d2da4c03 100644 --- a/tests/cases/fourslash/findAllRefsOnImportAliases2.ts +++ b/tests/cases/fourslash/findAllRefsOnImportAliases2.ts @@ -1,15 +1,23 @@ /// //@Filename: a.ts -////export class [|Class|] { +////export class [|{| "isWriteAccess": true, "isDefinition": true |}Class|] { ////} //@Filename: b.ts -////import { [|Class|] as [|C2|] } from "./a"; +////import { [|{| "isWriteAccess": true, "isDefinition": true |}Class|] as [|{| "isWriteAccess": true, "isDefinition": true |}C2|] } from "./a"; //// ////var c = new [|C2|](); //@Filename: c.ts -////export { [|Class|] as [|C3|] } from "./a"; +////export { [|{| "isWriteAccess": true, "isDefinition": true |}Class|] as [|{| "isWriteAccess": true, "isDefinition": true |}C3|] } from "./a"; -verify.rangesWithSameTextReferenceEachOther(); +const ranges = test.rangesByText(); +verify.singleReferenceGroup("class Class", ranges.get("Class")); + +const c2s = ranges.get("C2"); +const [c2_0, c2_1] = c2s; +verify.referenceGroups(c2_0, [{ definition: "import C2", ranges: c2s }]); +verify.referenceGroups(c2_1, [{ definition: "(alias) new C2(): C2\nimport C2", ranges: c2s }]); + +verify.singleReferenceGroup("import C3", ranges.get("C3")); diff --git a/tests/cases/fourslash/findAllRefsOnPrivateParameterProperty1.ts b/tests/cases/fourslash/findAllRefsOnPrivateParameterProperty1.ts index 3b8b5084a6b..df33f2888e6 100644 --- a/tests/cases/fourslash/findAllRefsOnPrivateParameterProperty1.ts +++ b/tests/cases/fourslash/findAllRefsOnPrivateParameterProperty1.ts @@ -1,7 +1,7 @@ /// ////class ABCD { -//// constructor(private x: number, public y: number, private [|z|]: number) { +//// constructor(private x: number, public y: number, private [|{| "isWriteAccess": true, "isDefinition": true |}z|]: number) { //// } //// //// func() { @@ -9,4 +9,4 @@ //// } ////} -verify.rangesReferenceEachOther(); +verify.singleReferenceGroup("(property) ABCD.z: number"); diff --git a/tests/cases/fourslash/findAllRefsParameterPropertyDeclaration1.ts b/tests/cases/fourslash/findAllRefsParameterPropertyDeclaration1.ts index 8f30e3cc853..fa1254118a1 100644 --- a/tests/cases/fourslash/findAllRefsParameterPropertyDeclaration1.ts +++ b/tests/cases/fourslash/findAllRefsParameterPropertyDeclaration1.ts @@ -1,10 +1,15 @@ /// //// class Foo { -//// constructor(private [|privateParam|]: number) { +//// constructor(private [|{| "isWriteAccess": true, "isDefinition": true |}privateParam|]: number) { //// let localPrivate = [|privateParam|]; //// this.[|privateParam|] += 10; //// } //// } -verify.rangesReferenceEachOther(); +const ranges = test.ranges(); +const [r0, r1, r2] = ranges; +verify.referenceGroups(ranges, [ + { definition: "(property) Foo.privateParam: number", ranges: [r0, r2] }, + { definition: "(parameter) privateParam: number", ranges: [r1] } +]); diff --git a/tests/cases/fourslash/findAllRefsParameterPropertyDeclaration2.ts b/tests/cases/fourslash/findAllRefsParameterPropertyDeclaration2.ts index d9656e8b5cf..45d814f909e 100644 --- a/tests/cases/fourslash/findAllRefsParameterPropertyDeclaration2.ts +++ b/tests/cases/fourslash/findAllRefsParameterPropertyDeclaration2.ts @@ -1,10 +1,15 @@ /// //// class Foo { -//// constructor(public [|publicParam|]: number) { +//// constructor(public [|{| "isWriteAccess": true, "isDefinition": true |}publicParam|]: number) { //// let localPublic = [|publicParam|]; //// this.[|publicParam|] += 10; //// } //// } -verify.rangesReferenceEachOther(); +const ranges = test.ranges(); +const [r0, r1, r2] = ranges; +verify.referenceGroups(ranges, [ + { definition: "(property) Foo.publicParam: number", ranges: [r0, r2] }, + { definition: "(parameter) publicParam: number", ranges: [r1] } +]); diff --git a/tests/cases/fourslash/findAllRefsParameterPropertyDeclaration3.ts b/tests/cases/fourslash/findAllRefsParameterPropertyDeclaration3.ts index dc48ffedb21..3520fecb8ad 100644 --- a/tests/cases/fourslash/findAllRefsParameterPropertyDeclaration3.ts +++ b/tests/cases/fourslash/findAllRefsParameterPropertyDeclaration3.ts @@ -1,10 +1,15 @@ /// //// class Foo { -//// constructor(protected [|protectedParam|]: number) { +//// constructor(protected [|{| "isWriteAccess": true, "isDefinition": true |}protectedParam|]: number) { //// let localProtected = [|protectedParam|]; //// this.[|protectedParam|] += 10; //// } //// } -verify.rangesReferenceEachOther(); +const ranges = test.ranges(); +const [r0, r1, r2] = ranges; +verify.referenceGroups(ranges, [ + { definition: "(property) Foo.protectedParam: number", ranges: [r0, r2] }, + { definition: "(parameter) protectedParam: number", ranges: [r1] } +]); diff --git a/tests/cases/fourslash/findAllRefsPrimitive.ts b/tests/cases/fourslash/findAllRefsPrimitive.ts index 51c463843e1..bf704c6ae71 100644 --- a/tests/cases/fourslash/findAllRefsPrimitive.ts +++ b/tests/cases/fourslash/findAllRefsPrimitive.ts @@ -24,7 +24,7 @@ // @Filename: b.ts // const z: [|any|] = 0; -verify.rangesWithSameTextReferenceEachOther(); +test.rangesByText().forEach((ranges, text) => verify.singleReferenceGroup(text, ranges)); verify.rangesWithSameTextAreDocumentHighlights(); goTo.rangeStart(test.ranges()[0]); diff --git a/tests/cases/fourslash/findAllRefsPropertyContextuallyTypedByTypeParam01.ts b/tests/cases/fourslash/findAllRefsPropertyContextuallyTypedByTypeParam01.ts index f5b0143ac4b..dec6575ebc4 100644 --- a/tests/cases/fourslash/findAllRefsPropertyContextuallyTypedByTypeParam01.ts +++ b/tests/cases/fourslash/findAllRefsPropertyContextuallyTypedByTypeParam01.ts @@ -1,12 +1,12 @@ /// ////interface IFoo { -//// [|a|]: string; +//// [|{| "isWriteAccess": true, "isDefinition": true |}a|]: string; ////} ////class C { //// method() { //// var x: T = { -//// [|a|]: "" +//// [|{| "isWriteAccess": true, "isDefinition": true |}a|]: "" //// }; //// x.[|a|]; //// } @@ -14,7 +14,17 @@ //// //// ////var x: IFoo = { -//// [|a|]: "ss" +//// [|{| "isWriteAccess": true, "isDefinition": true |}a|]: "ss" ////}; -verify.rangesReferenceEachOther(); +const ranges = test.ranges(); +const [r0, r1, r2, r3] = ranges; +verify.referenceGroups([r0, r2], [{ definition: "(property) IFoo.a: string", ranges }]); +verify.referenceGroups(r1, [ + { definition: "(property) IFoo.a: string", ranges: [r0, r2, r3] }, + { definition: "(property) a: string", ranges: [r1] } +]); +verify.referenceGroups(r3, [ + { definition: "(property) IFoo.a: string", ranges: [r0, r1, r2] }, + { definition: "(property) a: string", ranges: [r3] } +]); diff --git a/tests/cases/fourslash/findAllRefsThisKeyword.ts b/tests/cases/fourslash/findAllRefsThisKeyword.ts index f08a70ccf65..6f5374f902a 100644 --- a/tests/cases/fourslash/findAllRefsThisKeyword.ts +++ b/tests/cases/fourslash/findAllRefsThisKeyword.ts @@ -2,9 +2,9 @@ // @noLib: true ////[|this|]; -////function f([|this|]) { +////function f([|{| "isWriteAccess": true, "isDefinition": true |}this|]) { //// return [|this|]; -//// function g([|this|]) { return [|this|]; } +//// function g([|{| "isWriteAccess": true, "isDefinition": true |}this|]) { return [|this|]; } ////} ////class C { //// static x() { @@ -21,13 +21,19 @@ //// } ////} ////// These are *not* real uses of the 'this' keyword, they are identifiers. -////const x = { [|this|]: 0 } +////const x = { [|{| "isWriteAccess": true, "isDefinition": true |}this|]: 0 } ////x.[|this|]; const [global, f0, f1, g0, g1, x, y, constructor, method, propDef, propUse] = test.ranges(); verify.referencesOf(global, [global]); -verify.rangesReferenceEachOther([f0, f1]); -verify.rangesReferenceEachOther([g0, g1]); -verify.rangesReferenceEachOther([x, y]); -verify.rangesReferenceEachOther([constructor, method]); -verify.rangesReferenceEachOther([propDef, propUse]); +verify.referenceGroups(f0, [{ definition: "(parameter) this: any", ranges: [f0, f1] }]); +verify.referenceGroups(f1, [{ definition: "this: any", ranges: [f0, f1] }]); +verify.referenceGroups(g0, [{ definition: "(parameter) this: any", ranges: [g0, g1] }]); +verify.referenceGroups(g1, [{ definition: "this: any", ranges: [g0, g1] }]); +verify.singleReferenceGroup("this: typeof C", [x, y]); +verify.singleReferenceGroup("this: this", [constructor, method]); +verify.referenceGroups(propDef, [{ definition: "(property) this: number", ranges: [propDef, propUse] }]); +verify.referenceGroups(propUse, [ + { definition: "(property) this: number", ranges: [propDef] }, + { definition: "(property) this: number", ranges: [propUse] }, +]); diff --git a/tests/cases/fourslash/findAllRefsWithLeadingUnderscoreNames1.ts b/tests/cases/fourslash/findAllRefsWithLeadingUnderscoreNames1.ts index 7cc47ee34ea..d2baf7c96b3 100644 --- a/tests/cases/fourslash/findAllRefsWithLeadingUnderscoreNames1.ts +++ b/tests/cases/fourslash/findAllRefsWithLeadingUnderscoreNames1.ts @@ -1,10 +1,16 @@ /// ////class Foo { -//// public [|_bar|]() { return 0; } +//// public [|{| "isWriteAccess": true, "isDefinition": true |}_bar|]() { return 0; } ////} //// ////var x: Foo; ////x.[|_bar|]; -verify.rangesReferenceEachOther(); +const ranges = test.ranges(); +const [r0, r1] = ranges; +verify.referenceGroups(r0, [{ definition: "(method) Foo._bar(): number", ranges }]); +verify.referenceGroups(r1, [ + { definition: "(method) Foo._bar(): number", ranges: [r0] }, + { definition: "(method) Foo._bar(): number", ranges: [r1] } +]); diff --git a/tests/cases/fourslash/findAllRefsWithLeadingUnderscoreNames2.ts b/tests/cases/fourslash/findAllRefsWithLeadingUnderscoreNames2.ts index d1449016b59..3f5cd9ddbed 100644 --- a/tests/cases/fourslash/findAllRefsWithLeadingUnderscoreNames2.ts +++ b/tests/cases/fourslash/findAllRefsWithLeadingUnderscoreNames2.ts @@ -1,10 +1,16 @@ /// ////class Foo { -//// public [|__bar|]() { return 0; } +//// public [|{| "isWriteAccess": true, "isDefinition": true |}__bar|]() { return 0; } ////} //// ////var x: Foo; ////x.[|__bar|]; -verify.rangesReferenceEachOther(); +const ranges = test.ranges(); +const [r0, r1] = ranges; +verify.referenceGroups(r0, [{ definition: "(method) Foo.__bar(): number", ranges }]); +verify.referenceGroups(r1, [ + { definition: "(method) Foo.__bar(): number", ranges: [r0] }, + { definition: "(method) Foo.__bar(): number", ranges: [r1] } +]); diff --git a/tests/cases/fourslash/findAllRefsWithLeadingUnderscoreNames3.ts b/tests/cases/fourslash/findAllRefsWithLeadingUnderscoreNames3.ts index e0d6f7f3456..e1870065325 100644 --- a/tests/cases/fourslash/findAllRefsWithLeadingUnderscoreNames3.ts +++ b/tests/cases/fourslash/findAllRefsWithLeadingUnderscoreNames3.ts @@ -1,10 +1,16 @@ /// ////class Foo { -//// public [|___bar|]() { return 0; } +//// public [|{| "isWriteAccess": true, "isDefinition": true |}___bar|]() { return 0; } ////} //// ////var x: Foo; ////x.[|___bar|]; -verify.rangesReferenceEachOther(); +const ranges = test.ranges(); +const [r0, r1] = ranges; +verify.referenceGroups(r0, [{ definition: "(method) Foo.___bar(): number", ranges }]); +verify.referenceGroups(r1, [ + { definition: "(method) Foo.___bar(): number", ranges: [r0] }, + { definition: "(method) Foo.___bar(): number", ranges: [r1] } +]); diff --git a/tests/cases/fourslash/findAllRefsWithLeadingUnderscoreNames4.ts b/tests/cases/fourslash/findAllRefsWithLeadingUnderscoreNames4.ts index 5a8de54db4d..74eef0ae989 100644 --- a/tests/cases/fourslash/findAllRefsWithLeadingUnderscoreNames4.ts +++ b/tests/cases/fourslash/findAllRefsWithLeadingUnderscoreNames4.ts @@ -1,10 +1,16 @@ /// ////class Foo { -//// public [|____bar|]() { return 0; } +//// public [|{| "isWriteAccess": true, "isDefinition": true |}____bar|]() { return 0; } ////} //// ////var x: Foo; ////x.[|____bar|]; -verify.rangesReferenceEachOther(); +const ranges = test.ranges(); +const [r0, r1] = ranges; +verify.referenceGroups(r0, [{ definition: "(method) Foo.____bar(): number", ranges }]); +verify.referenceGroups(r1, [ + { definition: "(method) Foo.____bar(): number", ranges: [r0] }, + { definition: "(method) Foo.____bar(): number", ranges: [r1] } +]); diff --git a/tests/cases/fourslash/findAllRefsWithLeadingUnderscoreNames5.ts b/tests/cases/fourslash/findAllRefsWithLeadingUnderscoreNames5.ts index 4ab28f164fe..d54b48bf662 100644 --- a/tests/cases/fourslash/findAllRefsWithLeadingUnderscoreNames5.ts +++ b/tests/cases/fourslash/findAllRefsWithLeadingUnderscoreNames5.ts @@ -3,7 +3,7 @@ ////class Foo { //// public _bar; //// public __bar; -//// public [|___bar|]; +//// public [|{| "isWriteAccess": true, "isDefinition": true |}___bar|]; //// public ____bar; ////} //// @@ -13,4 +13,4 @@ ////x.[|___bar|]; ////x.____bar; -verify.rangesReferenceEachOther(); +verify.singleReferenceGroup("(property) Foo.___bar: any"); diff --git a/tests/cases/fourslash/findAllRefsWithLeadingUnderscoreNames6.ts b/tests/cases/fourslash/findAllRefsWithLeadingUnderscoreNames6.ts index 191b0bdbc14..39bc1d73ca3 100644 --- a/tests/cases/fourslash/findAllRefsWithLeadingUnderscoreNames6.ts +++ b/tests/cases/fourslash/findAllRefsWithLeadingUnderscoreNames6.ts @@ -2,7 +2,7 @@ ////class Foo { //// public _bar; -//// public [|__bar|]; +//// public [|{| "isWriteAccess": true, "isDefinition": true |}__bar|]; //// public ___bar; //// public ____bar; ////} @@ -13,4 +13,4 @@ ////x.___bar; ////x.____bar; -verify.rangesReferenceEachOther(); +verify.singleReferenceGroup("(property) Foo.__bar: any"); diff --git a/tests/cases/fourslash/findAllRefsWithLeadingUnderscoreNames7.ts b/tests/cases/fourslash/findAllRefsWithLeadingUnderscoreNames7.ts index f3578193096..dac42f4fc7c 100644 --- a/tests/cases/fourslash/findAllRefsWithLeadingUnderscoreNames7.ts +++ b/tests/cases/fourslash/findAllRefsWithLeadingUnderscoreNames7.ts @@ -1,7 +1,7 @@ /// -////function [|__foo|]() { +////function [|{| "isWriteAccess": true, "isDefinition": true |}__foo|]() { //// [|__foo|](); ////} -verify.rangesReferenceEachOther(); +verify.singleReferenceGroup("function __foo(): void"); diff --git a/tests/cases/fourslash/findAllRefsWithLeadingUnderscoreNames8.ts b/tests/cases/fourslash/findAllRefsWithLeadingUnderscoreNames8.ts index 15c66f4e7c6..8c92275e27f 100644 --- a/tests/cases/fourslash/findAllRefsWithLeadingUnderscoreNames8.ts +++ b/tests/cases/fourslash/findAllRefsWithLeadingUnderscoreNames8.ts @@ -1,7 +1,7 @@ /// -////(function [|__foo|]() { +////(function [|{| "isWriteAccess": true, "isDefinition": true |}__foo|]() { //// [|__foo|](); ////}) -verify.rangesReferenceEachOther(); +verify.singleReferenceGroup("(local function) __foo(): void"); diff --git a/tests/cases/fourslash/findAllRefsWithLeadingUnderscoreNames9.ts b/tests/cases/fourslash/findAllRefsWithLeadingUnderscoreNames9.ts index cc33b618c41..bc5799e61cf 100644 --- a/tests/cases/fourslash/findAllRefsWithLeadingUnderscoreNames9.ts +++ b/tests/cases/fourslash/findAllRefsWithLeadingUnderscoreNames9.ts @@ -1,7 +1,7 @@ /// -////(function [|___foo|]() { +////(function [|{| "isWriteAccess": true, "isDefinition": true |}___foo|]() { //// [|___foo|](); ////}) -verify.rangesReferenceEachOther(); +verify.singleReferenceGroup("(local function) ___foo(): void"); diff --git a/tests/cases/fourslash/findAllRefsWithShorthandPropertyAssignment.ts b/tests/cases/fourslash/findAllRefsWithShorthandPropertyAssignment.ts index 0dc050602c5..544a3238e3b 100644 --- a/tests/cases/fourslash/findAllRefsWithShorthandPropertyAssignment.ts +++ b/tests/cases/fourslash/findAllRefsWithShorthandPropertyAssignment.ts @@ -1,14 +1,19 @@ /// -//// var [|name|] = "Foo"; +//// var [|{| "isWriteAccess": true, "isDefinition": true |}name|] = "Foo"; //// -//// var obj = { [|name|] }; -//// var obj1 = { [|name|]:[|name|] }; +//// var obj = { [|{| "isWriteAccess": true, "isDefinition": true |}name|] }; +//// var obj1 = { [|{| "isWriteAccess": true, "isDefinition": true |}name|]:[|name|] }; //// obj.[|name|]; const [r0, r1, r2, r3, r4] = test.ranges(); -verify.referencesOf(r0, [r0, r1, r3]); -verify.referencesOf(r1, [r0, r1, r3, r4]); -verify.referencesOf(r2, [r2]); -verify.referencesOf(r3, [r0, r1, r3]); -verify.referencesOf(r4, [r1, r4]); +verify.referenceGroups([r0, r3], [{ definition: "var name: string", ranges: [r0, r1, r3] }]); +verify.referenceGroups(r1, [ + { definition: "var name: string", ranges: [r0, r3] }, + { definition: "(property) name: string", ranges: [r1, r4] } +]); +verify.singleReferenceGroup("(property) name: string", [r2]); +verify.referenceGroups(r4, [ + { definition: "(property) name: string", ranges: [r1] }, + { definition: "(property) name: string", ranges: [r4] }, +]); diff --git a/tests/cases/fourslash/findAllRefsWithShorthandPropertyAssignment2.ts b/tests/cases/fourslash/findAllRefsWithShorthandPropertyAssignment2.ts index 59ba87fabb6..d4f758696fe 100644 --- a/tests/cases/fourslash/findAllRefsWithShorthandPropertyAssignment2.ts +++ b/tests/cases/fourslash/findAllRefsWithShorthandPropertyAssignment2.ts @@ -1,16 +1,22 @@ /// -//// var [|dx|] = "Foo"; +//// var [|{| "isWriteAccess": true, "isDefinition": true |}dx|] = "Foo"; //// -//// module M { export var [|dx|]; } +//// module M { export var [|{| "isWriteAccess": true, "isDefinition": true |}dx|]; } //// module M { //// var z = 100; -//// export var y = { [|dx|], z }; +//// export var y = { [|{| "isWriteAccess": true, "isDefinition": true |}dx|], z }; //// } //// M.y.[|dx|]; const [r0, r1, r2, r3] = test.ranges(); -verify.referencesOf(r0, [r0]); -verify.referencesOf(r1, [r1, r2]); -verify.referencesOf(r2, [r1, r2, r3]); -verify.referencesOf(r3, [r2, r3]); +verify.singleReferenceGroup("var dx: string", [r0]); +verify.referenceGroups(r1, [{ definition: "var M.dx: any", ranges: [r1, r2] }]); +verify.referenceGroups(r2, [ + { definition: "var M.dx: any", ranges: [r1] }, + { definition: "(property) dx: any", ranges: [r2, r3] } +]); +verify.referenceGroups(r3, [ + { definition: "(property) dx: any", ranges: [r2] }, + { definition: "(property) dx: any", ranges: [r3] } +]); diff --git a/tests/cases/fourslash/findReferencesAcrossMultipleProjects.ts b/tests/cases/fourslash/findReferencesAcrossMultipleProjects.ts index a9915fc4b3d..f9feb5ddb62 100644 --- a/tests/cases/fourslash/findReferencesAcrossMultipleProjects.ts +++ b/tests/cases/fourslash/findReferencesAcrossMultipleProjects.ts @@ -1,14 +1,14 @@ /// //@Filename: a.ts -////var [|x|]: number; +////var [|{| "isWriteAccess": true, "isDefinition": true |}x|]: number; //@Filename: b.ts /////// -////[|x|]++; +////[|{| "isWriteAccess": true |}x|]++; //@Filename: c.ts /////// -////[|x|]++; +////[|{| "isWriteAccess": true |}x|]++; -verify.rangesReferenceEachOther(); +verify.singleReferenceGroup("var x: number"); diff --git a/tests/cases/fourslash/findReferencesAfterEdit.ts b/tests/cases/fourslash/findReferencesAfterEdit.ts index 6140ca9a767..2d57e78c637 100644 --- a/tests/cases/fourslash/findReferencesAfterEdit.ts +++ b/tests/cases/fourslash/findReferencesAfterEdit.ts @@ -2,7 +2,7 @@ // @Filename: a.ts ////interface A { -//// [|foo|]: string; +//// [|{| "isWriteAccess": true, "isDefinition": true |}foo|]: string; ////} // @Filename: b.ts @@ -12,9 +12,9 @@ //// x.[|foo|] ////} -verify.rangesReferenceEachOther(); +verify.singleReferenceGroup("(property) A.foo: string"); goTo.marker(""); edit.insert("\r\n"); -verify.rangesReferenceEachOther(); +verify.singleReferenceGroup("(property) A.foo: string"); diff --git a/tests/cases/fourslash/findReferencesJSXTagName.ts b/tests/cases/fourslash/findReferencesJSXTagName.ts index 24760046eb2..5f8bc3a475f 100644 --- a/tests/cases/fourslash/findReferencesJSXTagName.ts +++ b/tests/cases/fourslash/findReferencesJSXTagName.ts @@ -1,14 +1,16 @@ /// // @Filename: index.tsx -////import { [|SubmissionComp|] } from "./RedditSubmission" +////import { [|{| "isWriteAccess": true, "isDefinition": true |}SubmissionComp|] } from "./RedditSubmission" ////function displaySubreddit(subreddit: string) { //// let components = submissions //// .map((value, index) => <[|SubmissionComp|] key={ index } elementPosition= { index } {...value.data} />); ////} // @Filename: RedditSubmission.ts -////export const [|SubmissionComp|] = (submission: SubmissionProps) => +////export const [|{| "isWriteAccess": true, "isDefinition": true |}SubmissionComp|] = (submission: SubmissionProps) => ////
; -verify.rangesReferenceEachOther(); +const ranges = test.ranges(); +const [r0, r1, r2] = ranges; +verify.referenceGroups(ranges, [{ definition: "const SubmissionComp: (submission: any) => any", ranges: [r2, r0, r1] }]); diff --git a/tests/cases/fourslash/findReferencesJSXTagName2.ts b/tests/cases/fourslash/findReferencesJSXTagName2.ts index 4ce08647c52..a8882b60088 100644 --- a/tests/cases/fourslash/findReferencesJSXTagName2.ts +++ b/tests/cases/fourslash/findReferencesJSXTagName2.ts @@ -1,7 +1,9 @@ /// // @Filename: index.tsx -////const [|obj|] = {Component: () =>
}; +////const [|{| "isWriteAccess": true, "isDefinition": true |}obj|] = {Component: () =>
}; ////const element = <[|obj|].Component/>; -verify.rangesReferenceEachOther(); +verify.singleReferenceGroup(`const obj: { + Component: () => any; +}`); diff --git a/tests/cases/fourslash/fourslash.ts b/tests/cases/fourslash/fourslash.ts index 6685bbc19c0..c613204f539 100644 --- a/tests/cases/fourslash/fourslash.ts +++ b/tests/cases/fourslash/fourslash.ts @@ -182,18 +182,19 @@ declare namespace FourSlashInterface { goToType(startMarkerNames: string | string[], endMarkerNames: string | string[]): void; verifyGetEmitOutputForCurrentFile(expected: string): void; verifyGetEmitOutputContentsForCurrentFile(expected: ts.OutputFile[]): void; + noReferences(markerNameOrRange?: string | Range): void; /** - * Asserts that the given ranges are the references from the current position. - * If ranges have markers, those markers may have "isDefinition" and "isWriteAccess" data - * (otherwise these properties pf the reference are not tested). - * Order of ranges does not matter. - */ - referencesAre(ranges: Range[]): void; - /** + * @deprecated, prefer 'referenceGroups' * Like `referencesAre`, but goes to `start` first. * `start` should be included in `references`. */ referencesOf(start: Range, references: Range[]): void; + /** + * For each of startRanges, asserts the ranges that are referenced from there. + * This uses the 'findReferences' command instead of 'getReferencesAtPosition', so references are grouped by their definition. + */ + referenceGroups(startRanges: Range | Range[], parts: Array<{ definition: string, ranges: Range[] }>): void; + singleReferenceGroup(definition: string, ranges?: Range[]): void; rangesAreOccurrences(isWriteAccess?: boolean): void; rangesAreRenameLocations(findInStrings?: boolean, findInComments?: boolean): void; /** @@ -202,7 +203,6 @@ declare namespace FourSlashInterface { */ rangesReferenceEachOther(ranges?: Range[]): void; findReferencesDefinitionDisplayPartsAtCaretAre(expected: ts.SymbolDisplayPart[]): void; - rangesWithSameTextReferenceEachOther(): void; currentParameterHelpArgumentNameIs(name: string): void; currentParameterSpanIs(parameter: string): void; currentParameterHelpArgumentDocCommentIs(docComment: string): void; diff --git a/tests/cases/fourslash/getOccurrencesIsDefinitionOfArrowFunction.ts b/tests/cases/fourslash/getOccurrencesIsDefinitionOfArrowFunction.ts index 57b4c14ffba..b1acb76ad2c 100644 --- a/tests/cases/fourslash/getOccurrencesIsDefinitionOfArrowFunction.ts +++ b/tests/cases/fourslash/getOccurrencesIsDefinitionOfArrowFunction.ts @@ -1,5 +1,5 @@ /// -////var [|{| "isDefinition": true |}f|] = x => x + 1; -////[|{| "isDefinition": false |}f|](12); +////var [|{| "isWriteAccess": true, "isDefinition": true |}f|] = x => x + 1; +////[|f|](12); -verify.rangesReferenceEachOther(); +verify.singleReferenceGroup("var f: (x: any) => any"); diff --git a/tests/cases/fourslash/getOccurrencesIsDefinitionOfBindingPattern.ts b/tests/cases/fourslash/getOccurrencesIsDefinitionOfBindingPattern.ts index e60921ec3b8..7725b2e94f8 100644 --- a/tests/cases/fourslash/getOccurrencesIsDefinitionOfBindingPattern.ts +++ b/tests/cases/fourslash/getOccurrencesIsDefinitionOfBindingPattern.ts @@ -1,5 +1,5 @@ /// -////const { [|{| "isDefinition": true |}x|], y } = { x: 1, y: 2 }; +////const { [|{| "isWriteAccess": true, "isDefinition": true |}x|], y } = { x: 1, y: 2 }; ////const z = [|{| "isDefinition": false |}x|]; -verify.rangesReferenceEachOther(); +verify.singleReferenceGroup("const x: number"); diff --git a/tests/cases/fourslash/getOccurrencesIsDefinitionOfClass.ts b/tests/cases/fourslash/getOccurrencesIsDefinitionOfClass.ts index 0a3c2e4231c..b39c11dfe6b 100644 --- a/tests/cases/fourslash/getOccurrencesIsDefinitionOfClass.ts +++ b/tests/cases/fourslash/getOccurrencesIsDefinitionOfClass.ts @@ -1,10 +1,13 @@ /// -////class [|{| "isDefinition": true |}C|] { +////class [|{| "isWriteAccess": true, "isDefinition": true |}C|] { //// n: number; //// constructor() { //// this.n = 12; //// } ////} -////let c = new [|{| "isDefinition": false |}C|](); +////let c = new [|C|](); -verify.rangesReferenceEachOther(); +const ranges = test.ranges(); +const [r0, r1] = ranges; +verify.referenceGroups(r0, [{ definition: "class C", ranges }]); +verify.referenceGroups(r1, [{ definition: "constructor C(): C", ranges }]); diff --git a/tests/cases/fourslash/getOccurrencesIsDefinitionOfComputedProperty.ts b/tests/cases/fourslash/getOccurrencesIsDefinitionOfComputedProperty.ts index 81df97eff2d..27c34e56600 100644 --- a/tests/cases/fourslash/getOccurrencesIsDefinitionOfComputedProperty.ts +++ b/tests/cases/fourslash/getOccurrencesIsDefinitionOfComputedProperty.ts @@ -1,7 +1,9 @@ /// -////let o = { ["/**/[|{| "isDefinition": true |}foo|]"]: 12 }; -////let y = o.[|{| "isDefinition": false |}foo|]; -////let z = o['[|{| "isDefinition": false |}foo|]']; +////let o = { ["[|{| "isDefinition": true |}foo|]"]: 12 }; +////let y = o.[|foo|]; +////let z = o['[|foo|]']; -goTo.marker(); -verify.referencesAre(test.ranges()); +const ranges = test.ranges(); +const [r0, r1, r2] = ranges; +verify.referenceGroups(r0, [{ definition: '(property) ["foo"]: number', ranges }]); +verify.referenceGroups([r1, r2], []); // TODO: fix diff --git a/tests/cases/fourslash/getOccurrencesIsDefinitionOfEnum.ts b/tests/cases/fourslash/getOccurrencesIsDefinitionOfEnum.ts index 5b77bf6158a..325674d8ee7 100644 --- a/tests/cases/fourslash/getOccurrencesIsDefinitionOfEnum.ts +++ b/tests/cases/fourslash/getOccurrencesIsDefinitionOfEnum.ts @@ -1,8 +1,8 @@ /// -////enum [|{| "isDefinition": true |}E|] { +////enum [|{| "isWriteAccess": true, "isDefinition": true |}E|] { //// First, //// Second ////} -////let first = [|{| "isDefinition": false |}E|].First; +////let first = [|E|].First; -verify.rangesReferenceEachOther(); +verify.singleReferenceGroup("enum E"); diff --git a/tests/cases/fourslash/getOccurrencesIsDefinitionOfExport.ts b/tests/cases/fourslash/getOccurrencesIsDefinitionOfExport.ts index 759df4fa383..9cdfb0aa0f7 100644 --- a/tests/cases/fourslash/getOccurrencesIsDefinitionOfExport.ts +++ b/tests/cases/fourslash/getOccurrencesIsDefinitionOfExport.ts @@ -1,8 +1,8 @@ /// // @Filename: m.ts -////export var [|{| "isDefinition": true |}x|] = 12; +////export var [|{| "isWriteAccess": true, "isDefinition": true |}x|] = 12; // @Filename: main.ts -////import { [|{| "isDefinition": true |}x|] } from "./m"; -////const y = [|{| "isDefinition": false |}x|]; +////import { [|{| "isWriteAccess": true, "isDefinition": true |}x|] } from "./m"; +////const y = [|x|]; -verify.rangesReferenceEachOther(); +verify.singleReferenceGroup("var x: number"); diff --git a/tests/cases/fourslash/getOccurrencesIsDefinitionOfFunction.ts b/tests/cases/fourslash/getOccurrencesIsDefinitionOfFunction.ts index 357ef088d61..4c91bc08ef8 100644 --- a/tests/cases/fourslash/getOccurrencesIsDefinitionOfFunction.ts +++ b/tests/cases/fourslash/getOccurrencesIsDefinitionOfFunction.ts @@ -1,6 +1,6 @@ /// -////function [|{| "isDefinition": true |}func|](x: number) { +////function [|{| "isWriteAccess": true, "isDefinition": true |}func|](x: number) { ////} -////[|{| "isDefinition": false |}func|](x) +////[|func|](x) -verify.rangesReferenceEachOther(); +verify.singleReferenceGroup("function func(x: number): void"); diff --git a/tests/cases/fourslash/getOccurrencesIsDefinitionOfInterface.ts b/tests/cases/fourslash/getOccurrencesIsDefinitionOfInterface.ts index b7117995d84..826890c4da9 100644 --- a/tests/cases/fourslash/getOccurrencesIsDefinitionOfInterface.ts +++ b/tests/cases/fourslash/getOccurrencesIsDefinitionOfInterface.ts @@ -1,7 +1,7 @@ /// -////interface [|{| "isDefinition": true |}I|] { +////interface [|{| "isWriteAccess": true, "isDefinition": true |}I|] { //// p: number; ////} -////let i: [|{| "isDefinition": false |}I|] = { p: 12 }; +////let i: [|I|] = { p: 12 }; -verify.rangesReferenceEachOther(); +verify.singleReferenceGroup("interface I"); diff --git a/tests/cases/fourslash/getOccurrencesIsDefinitionOfInterfaceClassMerge.ts b/tests/cases/fourslash/getOccurrencesIsDefinitionOfInterfaceClassMerge.ts index b0506490c70..0e949ca6496 100644 --- a/tests/cases/fourslash/getOccurrencesIsDefinitionOfInterfaceClassMerge.ts +++ b/tests/cases/fourslash/getOccurrencesIsDefinitionOfInterfaceClassMerge.ts @@ -1,16 +1,19 @@ /// -////interface [|{| "isDefinition": true |}Numbers|] { +////interface [|{| "isWriteAccess": true, "isDefinition": true |}Numbers|] { //// p: number; ////} -////interface [|{| "isDefinition": true |}Numbers|] { +////interface [|{| "isWriteAccess": true, "isDefinition": true |}Numbers|] { //// m: number; ////} -////class [|{| "isDefinition": true |}Numbers|] { +////class [|{| "isWriteAccess": true, "isDefinition": true |}Numbers|] { //// f(n: number) { //// return this.p + this.m + n; //// } ////} -////let i: [|{| "isDefinition": false |}Numbers|] = new [|{| "isDefinition": false |}Numbers|](); +////let i: [|Numbers|] = new [|Numbers|](); ////let x = i.f(i.p + i.m); -verify.rangesReferenceEachOther(); +const ranges = test.ranges(); +const [r0, r1, r2, r3, r4] = ranges; +verify.referenceGroups([r0, r1, r2, r3], [{ definition: "class Numbers\ninterface Numbers", ranges }]); +verify.referenceGroups(r4, [{ definition: "constructor Numbers(): Numbers", ranges }]); diff --git a/tests/cases/fourslash/getOccurrencesIsDefinitionOfNamespace.ts b/tests/cases/fourslash/getOccurrencesIsDefinitionOfNamespace.ts index ff1cf00fa9b..04d00e6c19f 100644 --- a/tests/cases/fourslash/getOccurrencesIsDefinitionOfNamespace.ts +++ b/tests/cases/fourslash/getOccurrencesIsDefinitionOfNamespace.ts @@ -1,7 +1,7 @@ /// -////namespace [|{| "isDefinition": true |}Numbers|] { +////namespace [|{| "isWriteAccess": true, "isDefinition": true |}Numbers|] { //// export var n = 12; ////} -////let x = [|{| "isDefinition": false |}Numbers|].n + 1; +////let x = [|Numbers|].n + 1; -verify.rangesReferenceEachOther(); +verify.singleReferenceGroup("namespace Numbers"); diff --git a/tests/cases/fourslash/getOccurrencesIsDefinitionOfNumberNamedProperty.ts b/tests/cases/fourslash/getOccurrencesIsDefinitionOfNumberNamedProperty.ts index a041dab435a..c603f398e5e 100644 --- a/tests/cases/fourslash/getOccurrencesIsDefinitionOfNumberNamedProperty.ts +++ b/tests/cases/fourslash/getOccurrencesIsDefinitionOfNumberNamedProperty.ts @@ -1,5 +1,11 @@ /// ////let o = { [|{| "isDefinition": true |}1|]: 12 }; -////let y = o[[|{| "isDefinition": false |}1|]]; +////let y = o[[|1|]]; -verify.rangesReferenceEachOther(); +const ranges = test.ranges(); +const [r0, r1] = ranges; +verify.referenceGroups(r0, [{ definition: "(property) 1: number", ranges }]); +verify.referenceGroups(r1, [ + { definition: "(property) 1: number", ranges: [r0] }, + { definition: "(property) 1: number", ranges: [r1] } +]); diff --git a/tests/cases/fourslash/getOccurrencesIsDefinitionOfParameter.ts b/tests/cases/fourslash/getOccurrencesIsDefinitionOfParameter.ts index cdcc47014fd..8afa67bfe64 100644 --- a/tests/cases/fourslash/getOccurrencesIsDefinitionOfParameter.ts +++ b/tests/cases/fourslash/getOccurrencesIsDefinitionOfParameter.ts @@ -1,6 +1,6 @@ /// -////function f([|{| "isDefinition": true |}x|]: number) { -//// return [|{| "isDefinition": false |}x|] + 1 +////function f([|{| "isWriteAccess": true, "isDefinition": true |}x|]: number) { +//// return [|x|] + 1 ////} -verify.rangesReferenceEachOther(); +verify.singleReferenceGroup("(parameter) x: number"); diff --git a/tests/cases/fourslash/getOccurrencesIsDefinitionOfStringNamedProperty.ts b/tests/cases/fourslash/getOccurrencesIsDefinitionOfStringNamedProperty.ts index 383cf49a2e3..43fe0c571fc 100644 --- a/tests/cases/fourslash/getOccurrencesIsDefinitionOfStringNamedProperty.ts +++ b/tests/cases/fourslash/getOccurrencesIsDefinitionOfStringNamedProperty.ts @@ -1,5 +1,11 @@ /// ////let o = { "[|{| "isDefinition": true |}x|]": 12 }; -////let y = o.[|{| "isDefinition": false |}x|]; +////let y = o.[|x|]; -verify.rangesReferenceEachOther(); +const ranges = test.ranges(); +const [r0, r1] = ranges; +verify.referenceGroups(r0, [{ definition: '(property) "x": number', ranges }]); +verify.referenceGroups(r1, [ + { definition: '(property) "x": number', ranges: [r0] }, + { definition: '(property) "x": number', ranges: [r1] }, +]); diff --git a/tests/cases/fourslash/getOccurrencesIsDefinitionOfTypeAlias.ts b/tests/cases/fourslash/getOccurrencesIsDefinitionOfTypeAlias.ts index 2bd66830c69..18a4ec0396c 100644 --- a/tests/cases/fourslash/getOccurrencesIsDefinitionOfTypeAlias.ts +++ b/tests/cases/fourslash/getOccurrencesIsDefinitionOfTypeAlias.ts @@ -1,5 +1,5 @@ /// -////type [|{| "isDefinition": true |}Alias|]= number; -////let n: [|{| "isDefinition": false |}Alias|] = 12; +////type [|{| "isWriteAccess": true, "isDefinition": true |}Alias|]= number; +////let n: [|Alias|] = 12; -verify.rangesReferenceEachOther(); +verify.singleReferenceGroup("type Alias = number"); diff --git a/tests/cases/fourslash/getOccurrencesIsDefinitionOfVariable.ts b/tests/cases/fourslash/getOccurrencesIsDefinitionOfVariable.ts index 78529186ad3..2faf5b53e1b 100644 --- a/tests/cases/fourslash/getOccurrencesIsDefinitionOfVariable.ts +++ b/tests/cases/fourslash/getOccurrencesIsDefinitionOfVariable.ts @@ -1,20 +1,20 @@ /// -////var [|{| "isDefinition": true |}x|] = 0; -////var assignmentRightHandSide = [|{| "isDefinition": false |}x|]; -////var assignmentRightHandSide2 = 1 + [|{| "isDefinition": false |}x|]; +////var [|{| "isWriteAccess": true, "isDefinition": true |}x|] = 0; +////var assignmentRightHandSide = [|x|]; +////var assignmentRightHandSide2 = 1 + [|x|]; //// -////[|{| "isDefinition": false |}x|] = 1; -////[|{| "isDefinition": false |}x|] = [|{| "isDefinition": false |}x|] + [|{| "isDefinition": false |}x|]; +////[|{| "isWriteAccess": true |}x|] = 1; +////[|{| "isWriteAccess": true |}x|] = [|x|] + [|x|]; //// -////[|{| "isDefinition": false |}x|] == 1; -////[|{| "isDefinition": false |}x|] <= 1; +////[|x|] == 1; +////[|x|] <= 1; //// -////var preIncrement = ++[|{| "isDefinition": false |}x|]; -////var postIncrement = [|{| "isDefinition": false |}x|]++; -////var preDecrement = --[|{| "isDefinition": false |}x|]; -////var postDecrement = [|{| "isDefinition": false |}x|]--; +////var preIncrement = ++[|{| "isWriteAccess": true |}x|]; +////var postIncrement = [|{| "isWriteAccess": true |}x|]++; +////var preDecrement = --[|{| "isWriteAccess": true |}x|]; +////var postDecrement = [|{| "isWriteAccess": true |}x|]--; //// -////[|{| "isDefinition": false |}x|] += 1; -////[|{| "isDefinition": false |}x|] <<= 1; +////[|{| "isWriteAccess": true |}x|] += 1; +////[|{| "isWriteAccess": true |}x|] <<= 1; -verify.rangesReferenceEachOther(); +verify.singleReferenceGroup("var x: number"); diff --git a/tests/cases/fourslash/hoverOverComment.ts b/tests/cases/fourslash/hoverOverComment.ts index 653eaedfcb7..fd1a7fcd9de 100644 --- a/tests/cases/fourslash/hoverOverComment.ts +++ b/tests/cases/fourslash/hoverOverComment.ts @@ -7,4 +7,4 @@ goTo.marker(); verify.quickInfoIs(""); verify.goToDefinitionIs([]); -verify.referencesAre([]); +verify.noReferences(); diff --git a/tests/cases/fourslash/localGetReferences.ts b/tests/cases/fourslash/localGetReferences.ts index d8e64be1ada..4648471648a 100644 --- a/tests/cases/fourslash/localGetReferences.ts +++ b/tests/cases/fourslash/localGetReferences.ts @@ -3,17 +3,17 @@ // @Filename: localGetReferences_1.ts ////// Comment Refence Test: g/*1*/lobalVar ////// References to a variable declared in global. -////var [|globalVar|]: number = 2; +////var [|{| "isWriteAccess": true, "isDefinition": true |}globalVar|]: number = 2; //// ////class fooCls { //// // References to static variable declared in a class. -//// static [|clsSVar|] = 1; +//// static [|{| "isWriteAccess": true, "isDefinition": true |}clsSVar|] = 1; //// // References to a variable declared in a class. -//// [|clsVar|] = 1; +//// [|{| "isWriteAccess": true, "isDefinition": true |}clsVar|] = 1; //// -//// constructor (public [|clsParam|]: number) { +//// constructor (public [|{| "isWriteAccess": true, "isDefinition": true |}clsParam|]: number) { //// //Increments -//// [|globalVar|]++; +//// [|{| "isWriteAccess": true |}globalVar|]++; //// this.[|clsVar|]++; //// fooCls.[|clsSVar|]++; //// // References to a class parameter. @@ -23,18 +23,18 @@ ////} //// ////// References to a function parameter. -////function [|foo|]([|x|]: number) { +////function [|{| "isWriteAccess": true, "isDefinition": true |}foo|]([|{| "isWriteAccess": true, "isDefinition": true |}x|]: number) { //// // References to a variable declared in a function. -//// var [|fnVar|] = 1; +//// var [|{| "isWriteAccess": true, "isDefinition": true |}fnVar|] = 1; //// //// //Increments //// fooCls.[|clsSVar|]++; -//// [|globalVar|]++; +//// [|{| "isWriteAccess": true |}globalVar|]++; //// modTest.modVar++; -//// [|fnVar|]++; +//// [|{| "isWriteAccess": true |}fnVar|]++; //// //// //Return -//// return [|x|]++; +//// return [|{| "isWriteAccess": true |}x|]++; ////} //// ////module modTest { @@ -42,7 +42,7 @@ //// export var modVar:number; //// //// //Increments -//// [|globalVar|]++; +//// [|{| "isWriteAccess": true |}globalVar|]++; //// fooCls.[|clsSVar|]++; //// modVar++; //// @@ -54,7 +54,7 @@ //// static boo = [|foo|]; //// //// //Increments -//// [|globalVar|]++; +//// [|{| "isWriteAccess": true |}globalVar|]++; //// fooCls.[|clsSVar|]++; //// modVar++; //// } @@ -76,18 +76,18 @@ //////Increments ////fooCls.[|clsSVar|]++; ////modTest.modVar++; -////[|globalVar|] = [|globalVar|] + [|globalVar|]; +////[|{| "isWriteAccess": true |}globalVar|] = [|globalVar|] + [|globalVar|]; //// //////ETC - Other cases -////[|globalVar|] = 3; +////[|{| "isWriteAccess": true |}globalVar|] = 3; ////// References to illegal assignment. -////[|foo|] = [|foo|] + 1; +////[|{| "isWriteAccess": true |}foo|] = [|foo|] + 1; /////*3*/err = err++; /////*4*/ //////Shadowed fn Parameter -////function shdw([|{| "shadow": true |}globalVar|]: number) { +////function shdw([|{| "isWriteAccess": true, "isDefinition": true, "shadow": true |}globalVar|]: number) { //// //Increments -//// [|{| "shadow": true |}globalVar|]++; +//// [|{| "isWriteAccess": true, "shadow": true |}globalVar|]++; //// return [|{| "shadow": true |}globalVar|]; ////} //// @@ -117,7 +117,7 @@ ////array.forEach( //// //// -////function([|str|]) { +////function([|{| "isWriteAccess": true, "isDefinition": true |}str|]) { //// //// //// @@ -187,24 +187,36 @@ // References to comment. goTo.marker("1"); -verify.referencesAre([]); +verify.noReferences(); // References to unresolved symbol. goTo.marker("3"); -verify.referencesAre([]); +verify.noReferences(); // References to no context. goTo.marker("4"); -verify.referencesAre([]); +verify.noReferences(); -const rangesByText = test.rangesByText(); -rangesByText.forEach((ranges, text) => { +test.rangesByText().forEach((ranges, text) => { if (text === "globalVar") { - verify.rangesReferenceEachOther(ranges.filter(isShadow)); - verify.rangesReferenceEachOther(ranges.filter(r => !isShadow(r))); - } else { - verify.rangesReferenceEachOther(ranges); + verify.singleReferenceGroup("(parameter) globalVar: number", ranges.filter(isShadow)); + verify.singleReferenceGroup("var globalVar: number", ranges.filter(r => !isShadow(r))); + return; } + + const definition = (() => { + switch (text) { + case "fnVar": return "(local var) fnVar: number"; + case "clsSVar": return "(property) fooCls.clsSVar: number"; + case "clsVar": return "(property) fooCls.clsVar: number"; + case "clsParam": return "(property) fooCls.clsParam: number"; + case "foo": return "function foo(x: number): number"; + case "x": return "(parameter) x: number"; + case "str": return "(parameter) str: string"; + default: throw new Error(text); + } + })(); + verify.singleReferenceGroup(definition, ranges); }); function isShadow(r) { diff --git a/tests/cases/fourslash/quickInfoForRequire.ts b/tests/cases/fourslash/quickInfoForRequire.ts index 26b0371fe0e..e97810401f4 100644 --- a/tests/cases/fourslash/quickInfoForRequire.ts +++ b/tests/cases/fourslash/quickInfoForRequire.ts @@ -6,5 +6,6 @@ //@Filename: quickInfoForRequire_input.ts ////import a = require("./AA/B/*1*/B"); -verify.quickInfoAt("1", "module a"); -verify.referencesAre([]); \ No newline at end of file +goTo.marker("1"); +verify.quickInfoIs("module a"); +verify.noReferences(); diff --git a/tests/cases/fourslash/referenceInParameterPropertyDeclaration.ts b/tests/cases/fourslash/referenceInParameterPropertyDeclaration.ts index 68a9f73b1d6..79bf6172863 100644 --- a/tests/cases/fourslash/referenceInParameterPropertyDeclaration.ts +++ b/tests/cases/fourslash/referenceInParameterPropertyDeclaration.ts @@ -2,19 +2,26 @@ // @Filename: file1.ts //// class Foo { -//// constructor(private [|privateParam|]: number, -//// public [|publicParam|]: string, -//// protected [|protectedParam|]: boolean) { -//// +//// constructor(private [|{| "isWriteAccess": true, "isDefinition": true, "type": "number" |}privateParam|]: number, +//// public [|{| "isWriteAccess": true, "isDefinition": true, "type": "string" |}publicParam|]: string, +//// protected [|{| "isWriteAccess": true, "isDefinition": true, "type": "boolean" |}protectedParam|]: boolean) { +//// //// let localPrivate = [|privateParam|]; //// this.[|privateParam|] += 10; -//// +//// //// let localPublic = [|publicParam|]; //// this.[|publicParam|] += " Hello!"; -//// +//// //// let localProtected = [|protectedParam|]; //// this.[|protectedParam|] = false; //// } //// } -verify.rangesWithSameTextReferenceEachOther(); +test.rangesByText().forEach((ranges, text) => { + const [r0, r1, r2] = ranges; + const type = r0.marker.data.type; + verify.referenceGroups(ranges, [ + { definition: `(property) Foo.${text}: ${type}`, ranges: [r0, r2] }, + { definition: `(parameter) ${text}: ${type}`, ranges: [r1] } + ]); +}); diff --git a/tests/cases/fourslash/referenceToClass.ts b/tests/cases/fourslash/referenceToClass.ts index 3e523487bd1..d6d2171507c 100644 --- a/tests/cases/fourslash/referenceToClass.ts +++ b/tests/cases/fourslash/referenceToClass.ts @@ -3,7 +3,7 @@ // Class references should work across file and not find local variables. // @Filename: referenceToClass_1.ts -////class [|foo|] { +////class [|{| "isWriteAccess": true, "isDefinition": true |}foo|] { //// public n: [|foo|]; //// public foo: number; ////} @@ -20,4 +20,7 @@ // @Filename: referenceToClass_2.ts ////var k: [|foo|]; -verify.rangesReferenceEachOther(); +const ranges = test.ranges(); +const [r0, r1, r2, r3, r4, r5] = ranges; +verify.referenceGroups([r0, r1, r2, r4, r5], [{ definition: "class foo", ranges }]); +verify.referenceGroups(r3, [{ definition: "constructor foo(): foo", ranges }]); diff --git a/tests/cases/fourslash/referencesBloomFilters.ts b/tests/cases/fourslash/referencesBloomFilters.ts index 7d99ccdfd3c..c9f290db0db 100644 --- a/tests/cases/fourslash/referencesBloomFilters.ts +++ b/tests/cases/fourslash/referencesBloomFilters.ts @@ -3,7 +3,7 @@ // Ensure BloomFilter building logic is correct, by having one reference per file // @Filename: declaration.ts -////var container = { [|searchProp|] : 1 }; +////var container = { [|{| "isWriteAccess": true, "isDefinition": true |}searchProp|] : 1 }; // @Filename: expression.ts ////function blah() { return (1 + 2 + container.[|searchProp|]()) === 2; }; @@ -12,6 +12,16 @@ ////function blah2() { container["[|searchProp|]"] }; // @Filename: redeclaration.ts -////container = { "[|searchProp|]" : 18 }; +////container = { "[|{| "isDefinition": true |}searchProp|]" : 18 }; -verify.rangesReferenceEachOther(); +const ranges = test.ranges(); +const [r0, r1, r2, r3] = ranges; +verify.referenceGroups(r0, [{ definition: "(property) searchProp: number", ranges }]); +verify.referenceGroups([r1, r2], [ + { definition: "(property) searchProp: number", ranges: [r0, r3] }, + { definition: "(property) searchProp: number", ranges: [r1, r2] } +]); +verify.referenceGroups(r3, [ + { definition: "(property) searchProp: number", ranges: [r0, r1, r2] }, + { definition: '(property) "searchProp": number', ranges: [r3] } +]); diff --git a/tests/cases/fourslash/referencesBloomFilters2.ts b/tests/cases/fourslash/referencesBloomFilters2.ts index c42e5d4eaf1..daf60d0dd01 100644 --- a/tests/cases/fourslash/referencesBloomFilters2.ts +++ b/tests/cases/fourslash/referencesBloomFilters2.ts @@ -3,7 +3,7 @@ // Ensure BloomFilter building logic is correct, by having one reference per file // @Filename: declaration.ts -////var container = { [|42|]: 1 }; +////var container = { [|{| "isDefinition": true |}42|]: 1 }; // @Filename: expression.ts ////function blah() { return (container[[|42|]]) === 2; }; @@ -12,6 +12,16 @@ ////function blah2() { container["[|42|]"] }; // @Filename: redeclaration.ts -////container = { "[|42|]" : 18 }; +////container = { "[|{| "isDefinition": true |}42|]" : 18 }; -verify.rangesReferenceEachOther(); +const ranges = test.ranges(); +const [r0, r1, r2, r3] = ranges; +verify.referenceGroups(r0, [{ definition: "(property) 42: number", ranges }]); +verify.referenceGroups([r1, r2], [ + { definition: "(property) 42: number", ranges: [r0, r3] }, + { definition: "(property) 42: number", ranges: [r1, r2] } +]); +verify.referenceGroups(r3, [ + { definition: "(property) 42: number", ranges: [r0, r1, r2] }, + { definition: '(property) "42": number', ranges: [r3] } +]); diff --git a/tests/cases/fourslash/referencesBloomFilters3.ts b/tests/cases/fourslash/referencesBloomFilters3.ts index 9703baceb12..0dd5c645264 100644 --- a/tests/cases/fourslash/referencesBloomFilters3.ts +++ b/tests/cases/fourslash/referencesBloomFilters3.ts @@ -4,9 +4,9 @@ // @Filename: declaration.ts -////enum Test { "[|42|]" = 1 }; +////enum Test { "[|{| "isDefinition": true |}42|]" = 1 }; // @Filename: expression.ts ////(Test[[|42|]]); -verify.rangesReferenceEachOther(); +verify.singleReferenceGroup('(enum member) Test["42"] = 1'); diff --git a/tests/cases/fourslash/referencesForAmbients.ts b/tests/cases/fourslash/referencesForAmbients.ts index da3f3f43aae..58e4d6e59a5 100644 --- a/tests/cases/fourslash/referencesForAmbients.ts +++ b/tests/cases/fourslash/referencesForAmbients.ts @@ -1,11 +1,11 @@ /// -////declare module "[|foo|]" { -//// var [|f|]: number; +////declare module "[|{| "isDefinition": true |}foo|]" { +//// var [|{| "isWriteAccess": true, "isDefinition": true |}f|]: number; ////} //// -////declare module "[|bar|]" { -//// export import [|foo|] = require("[|foo|]"); +////declare module "[|{| "isDefinition": true |}bar|]" { +//// export import [|{| "isWriteAccess": true, "isDefinition": true |}foo|] = require("[|foo|]"); //// var f2: typeof [|foo|].[|f|]; ////} //// @@ -15,7 +15,7 @@ ////} const [moduleFoo0, f0, moduleBar0, foo0, moduleFoo1, foo1, f1, moduleBar1, foo2] = test.ranges(); -verify.rangesReferenceEachOther([moduleFoo0, moduleFoo1]); -verify.rangesReferenceEachOther([moduleBar0, moduleBar1]); -verify.rangesReferenceEachOther([foo0, foo1, foo2]); -verify.rangesReferenceEachOther([f0, f1]); +verify.singleReferenceGroup('module "foo"', [moduleFoo0, moduleFoo1]); +verify.singleReferenceGroup('module "bar"', [moduleBar0, moduleBar1]); +verify.singleReferenceGroup('import foo = require("foo")', [foo0, foo1, foo2]); +verify.singleReferenceGroup("var f: number", [f0, f1]); diff --git a/tests/cases/fourslash/referencesForClassLocal.ts b/tests/cases/fourslash/referencesForClassLocal.ts index bdde0e7f126..4108c060a39 100644 --- a/tests/cases/fourslash/referencesForClassLocal.ts +++ b/tests/cases/fourslash/referencesForClassLocal.ts @@ -5,7 +5,7 @@ ////var n = 14; //// ////class foo { -//// private [|n|] = 0; +//// private [|{| "isWriteAccess": true, "isDefinition": true |}n|] = 0; //// //// public bar() { //// this.[|n|] = 9; @@ -20,4 +20,4 @@ //// } ////} -verify.rangesReferenceEachOther(); +verify.singleReferenceGroup("(property) foo.n: number"); diff --git a/tests/cases/fourslash/referencesForClassMembers.ts b/tests/cases/fourslash/referencesForClassMembers.ts index 0208b13589d..0db4ebb0873 100644 --- a/tests/cases/fourslash/referencesForClassMembers.ts +++ b/tests/cases/fourslash/referencesForClassMembers.ts @@ -1,16 +1,36 @@ /// ////class Base { -//// [|a|]: number; -//// [|method|](): void { } +//// [|{| "isWriteAccess": true, "isDefinition": true |}a|]: number; +//// [|{| "isWriteAccess": true, "isDefinition": true |}method|](): void { } ////} ////class MyClass extends Base { -//// [|a|]; -//// [|method|]() { } +//// [|{| "isWriteAccess": true, "isDefinition": true |}a|]; +//// [|{| "isWriteAccess": true, "isDefinition": true |}method|]() { } ////} //// ////var c: MyClass; ////c.[|a|]; ////c.[|method|](); -verify.rangesWithSameTextReferenceEachOther(); +const ranges = test.rangesByText(); +const properties = ranges.get("a"); +const [a0, a1, a2] = properties; +verify.referenceGroups(a0, [{ definition: "(property) Base.a: number", ranges: properties }]); +verify.referenceGroups([a1, a2], [ + { definition: "(property) Base.a: number", ranges: [a0] }, + { definition: "(property) MyClass.a: any", ranges: [a1, a2] } +]); + +const methods = ranges.get("method"); +const [m0, m1, m2] = methods; +verify.referenceGroups(m0, [{ definition: "(method) Base.method(): void", ranges: methods }]); +verify.referenceGroups(m1, [ + { definition: "(method) Base.method(): void", ranges: [m0] }, + { definition: "(method) MyClass.method(): void", ranges: [m1, m2] } +]); +verify.referenceGroups(m2, [ + { definition: "(method) Base.method(): void", ranges: [m0] }, + { definition: "(method) MyClass.method(): void", ranges: [m1] }, + { definition: "(method) MyClass.method(): void", ranges: [m2] } +]); diff --git a/tests/cases/fourslash/referencesForClassMembersExtendingAbstractClass.ts b/tests/cases/fourslash/referencesForClassMembersExtendingAbstractClass.ts index 46115f9da17..b5be77a73bb 100644 --- a/tests/cases/fourslash/referencesForClassMembersExtendingAbstractClass.ts +++ b/tests/cases/fourslash/referencesForClassMembersExtendingAbstractClass.ts @@ -1,16 +1,36 @@ /// ////abstract class Base { -//// abstract [|a|]: number; -//// abstract [|method|](): void; +//// abstract [|{| "isWriteAccess": true, "isDefinition": true |}a|]: number; +//// abstract [|{| "isWriteAccess": true, "isDefinition": true |}method|](): void; ////} ////class MyClass extends Base { -//// [|a|]; -//// [|method|]() { } +//// [|{| "isWriteAccess": true, "isDefinition": true |}a|]; +//// [|{| "isWriteAccess": true, "isDefinition": true |}method|]() { } ////} //// ////var c: MyClass; ////c.[|a|]; ////c.[|method|](); -verify.rangesWithSameTextReferenceEachOther(); +const ranges = test.rangesByText(); +const properties = ranges.get("a"); +const [a0, a1, a2] = properties; +verify.referenceGroups(a0, [{ definition: "(property) Base.a: number", ranges: properties }]); +verify.referenceGroups([a1, a2], [ + { definition: "(property) Base.a: number", ranges: [a0] }, + { definition: "(property) MyClass.a: any", ranges: [a1, a2] } +]); + +const methods = ranges.get("method"); +const [m0, m1, m2] = methods; +verify.referenceGroups(m0, [{ definition: "(method) Base.method(): void", ranges: methods }]); +verify.referenceGroups(m1, [ + { definition: "(method) Base.method(): void", ranges: [m0] }, + { definition: "(method) MyClass.method(): void", ranges: [m1, m2] } +]); +verify.referenceGroups(m2, [ + { definition: "(method) Base.method(): void", ranges: [m0] }, + { definition: "(method) MyClass.method(): void", ranges: [m1] }, + { definition: "(method) MyClass.method(): void", ranges: [m2] } +]); diff --git a/tests/cases/fourslash/referencesForClassMembersExtendingGenericClass.ts b/tests/cases/fourslash/referencesForClassMembersExtendingGenericClass.ts index 2b701f25cc1..3e453663f63 100644 --- a/tests/cases/fourslash/referencesForClassMembersExtendingGenericClass.ts +++ b/tests/cases/fourslash/referencesForClassMembersExtendingGenericClass.ts @@ -1,16 +1,36 @@ /// ////class Base { -//// [|a|]: this; -//// [|method|](a?:T, b?:U): this { } +//// [|{| "isWriteAccess": true, "isDefinition": true |}a|]: this; +//// [|{| "isWriteAccess": true, "isDefinition": true |}method|](a?:T, b?:U): this { } ////} ////class MyClass extends Base { -//// [|a|]; -//// [|method|]() { } +//// [|{| "isWriteAccess": true, "isDefinition": true |}a|]; +//// [|{| "isWriteAccess": true, "isDefinition": true |}method|]() { } ////} //// ////var c: MyClass; ////c.[|a|]; ////c.[|method|](); -verify.rangesWithSameTextReferenceEachOther(); +const ranges = test.rangesByText(); +const properties = ranges.get("a"); +const [a0, a1, a2] = properties; +verify.referenceGroups(a0, [{ definition: "(property) Base.a: this", ranges: properties }]); +verify.referenceGroups([a1, a2], [ + { definition: "(property) Base.a: this", ranges: [a0] }, + { definition: "(property) MyClass.a: any", ranges: [a1, a2] } +]); + +const methods = ranges.get("method"); +const [m0, m1, m2] = methods; +verify.referenceGroups(m0, [{ definition: "(method) Base.method(a?: T, b?: U): this", ranges: methods }]); +verify.referenceGroups(m1, [ + { definition: "(method) Base.method(): void", ranges: [m0] }, + { definition: "(method) MyClass.method(): void", ranges: [m1, m2] } +]); +verify.referenceGroups(m2, [ + { definition: "(method) Base.method(a?: T, b?: U): this", ranges: [m0] }, + { definition: "(method) MyClass.method(): void", ranges: [m1] }, + { definition: "(method) MyClass.method(): void", ranges: [m2] } +]); diff --git a/tests/cases/fourslash/referencesForClassParameter.ts b/tests/cases/fourslash/referencesForClassParameter.ts index ce383b36503..e1a33dc5ac4 100644 --- a/tests/cases/fourslash/referencesForClassParameter.ts +++ b/tests/cases/fourslash/referencesForClassParameter.ts @@ -7,7 +7,7 @@ ////class p { } //// ////class foo { -//// constructor (public [|p|]: any) { +//// constructor (public [|{| "isWriteAccess": true, "isDefinition": true |}p|]: any) { //// } //// //// public f(p) { @@ -19,4 +19,10 @@ ////var n = new foo(undefined); ////n.[|p|] = null; -verify.rangesReferenceEachOther(); +const ranges = test.ranges(); +const [r0, r1, r2] = ranges; +verify.referenceGroups([r0, r1], [{ definition: "(property) foo.p: any", ranges }]); +verify.referenceGroups(r2, [ + { definition: "(property) foo.p: any", ranges: [r0, r1] }, + { definition: "(property) foo.p: any", ranges: [r2] } +]); diff --git a/tests/cases/fourslash/referencesForContextuallyTypedObjectLiteralProperties.ts b/tests/cases/fourslash/referencesForContextuallyTypedObjectLiteralProperties.ts index 65bd7eebfb5..7d6bc05cf30 100644 --- a/tests/cases/fourslash/referencesForContextuallyTypedObjectLiteralProperties.ts +++ b/tests/cases/fourslash/referencesForContextuallyTypedObjectLiteralProperties.ts @@ -1,28 +1,36 @@ /// -////interface IFoo { [|xy|]: number; } +////interface IFoo { [|{| "isWriteAccess": true, "isDefinition": true |}xy|]: number; } //// ////// Assignment -////var a1: IFoo = { [|xy|]: 0 }; -////var a2: IFoo = { [|xy|]: 0 }; +////var a1: IFoo = { [|{| "isWriteAccess": true, "isDefinition": true |}xy|]: 0 }; +////var a2: IFoo = { [|{| "isWriteAccess": true, "isDefinition": true |}xy|]: 0 }; //// ////// Function call ////function consumer(f: IFoo) { } -////consumer({ [|xy|]: 1 }); +////consumer({ [|{| "isWriteAccess": true, "isDefinition": true |}xy|]: 1 }); //// -////// Type cast -////var c = { [|xy|]: 0 }; +////// Type cast +////var c = { [|{| "isWriteAccess": true, "isDefinition": true |}xy|]: 0 }; //// ////// Array literal -////var ar: IFoo[] = [{ [|xy|]: 1 }, { [|xy|]: 2 }]; +////var ar: IFoo[] = [{ [|{| "isWriteAccess": true, "isDefinition": true |}xy|]: 1 }, { [|{| "isWriteAccess": true, "isDefinition": true |}xy|]: 2 }]; //// ////// Nested object literal -////var ob: { ifoo: IFoo } = { ifoo: { [|xy|]: 0 } }; +////var ob: { ifoo: IFoo } = { ifoo: { [|{| "isWriteAccess": true, "isDefinition": true |}xy|]: 0 } }; //// ////// Widened type -////var w: IFoo = { [|xy|]: undefined }; +////var w: IFoo = { [|{| "isWriteAccess": true, "isDefinition": true, "type": "undefined" |}xy|]: undefined }; //// ////// Untped -- should not be included ////var u = { xy: 0 }; -verify.rangesReferenceEachOther(); +const ranges = test.ranges(); +verify.referenceGroups(ranges[0], [{ definition: "(property) IFoo.xy: number", ranges }]); +for (const range of ranges.slice(1)) { + const type = range.marker.data.type || "number"; + verify.referenceGroups(range, [ + { definition: "(property) IFoo.xy: number", ranges: ranges.filter(r => r !== range) }, + { definition: `(property) xy: ${type}`, ranges: [range] } + ]); +} diff --git a/tests/cases/fourslash/referencesForContextuallyTypedUnionProperties.ts b/tests/cases/fourslash/referencesForContextuallyTypedUnionProperties.ts index c0e4a5f90ea..d79d4097ee7 100644 --- a/tests/cases/fourslash/referencesForContextuallyTypedUnionProperties.ts +++ b/tests/cases/fourslash/referencesForContextuallyTypedUnionProperties.ts @@ -2,33 +2,33 @@ ////interface A { //// a: number; -//// [|common|]: string; +//// [|{| "isWriteAccess": true, "isDefinition": true |}common|]: string; ////} //// ////interface B { //// b: number; -//// [|common|]: number; +//// [|{| "isWriteAccess": true, "isDefinition": true |}common|]: number; ////} //// ////// Assignment -////var v1: A | B = { a: 0, [|common|]: "" }; -////var v2: A | B = { b: 0, [|common|]: 3 }; +////var v1: A | B = { a: 0, [|{| "isWriteAccess": true, "isDefinition": true, "type": "string" |}common|]: "" }; +////var v2: A | B = { b: 0, [|{| "isWriteAccess": true, "isDefinition": true, "type": "number" |}common|]: 3 }; //// ////// Function call ////function consumer(f: A | B) { } -////consumer({ a: 0, b: 0, [|common|]: 1 }); +////consumer({ a: 0, b: 0, [|{| "isWriteAccess": true, "isDefinition": true, "type": "number" |}common|]: 1 }); //// -////// Type cast -////var c = { [|common|]: 0, b: 0 }; +////// Type cast +////var c = { [|{| "isWriteAccess": true, "isDefinition": true, "type": "number" |}common|]: 0, b: 0 }; //// ////// Array literal -////var ar: Array = [{ a: 0, [|common|]: "" }, { b: 0, [|common|]: 0 }]; +////var ar: Array = [{ a: 0, [|{| "isWriteAccess": true, "isDefinition": true, "type": "string" |}common|]: "" }, { b: 0, [|{| "isWriteAccess": true, "isDefinition": true, "type": "number" |}common|]: 0 }]; //// ////// Nested object literal -////var ob: { aorb: A|B } = { aorb: { b: 0, [|common|]: 0 } }; +////var ob: { aorb: A|B } = { aorb: { b: 0, [|{| "isWriteAccess": true, "isDefinition": true, "type": "number" |}common|]: 0 } }; //// ////// Widened type -////var w: A|B = { a:0, [|common|]: undefined }; +////var w: A|B = { a:0, [|{| "isWriteAccess": true, "isDefinition": true, "type": "undefined" |}common|]: undefined }; //// ////// Untped -- should not be included ////var u1 = { a: 0, b: 0, common: "" }; @@ -36,8 +36,14 @@ const all = test.ranges(); const [aCommon, bCommon, ...unionRefs] = all; -verify.referencesOf(aCommon, [aCommon, ...unionRefs]); -verify.referencesOf(bCommon, [bCommon, ...unionRefs]); -for (const ref of unionRefs) { - verify.referencesOf(ref, all); -} +verify.referenceGroups(aCommon, [{ definition: "(property) A.common: string", ranges: [aCommon, ...unionRefs] }]); +verify.referenceGroups(bCommon, [{ definition: "(property) B.common: number", ranges: [bCommon, ...unionRefs] }]); + +unionRefs.forEach((unionRef, idx) => { + const type = unionRef.marker.data.type; + verify.referenceGroups(unionRef, [ + { definition: "(property) A.common: string", ranges: all.filter(x => x !== bCommon && x !== unionRef) }, + { definition: "(property) B.common: number", ranges: [bCommon] }, + { definition: `(property) common: ${type}`, ranges: [unionRef] } + ]); +}); diff --git a/tests/cases/fourslash/referencesForContextuallyTypedUnionProperties2.ts b/tests/cases/fourslash/referencesForContextuallyTypedUnionProperties2.ts index de9ffbfd3be..2c48e353b03 100644 --- a/tests/cases/fourslash/referencesForContextuallyTypedUnionProperties2.ts +++ b/tests/cases/fourslash/referencesForContextuallyTypedUnionProperties2.ts @@ -6,32 +6,40 @@ ////} //// ////interface B { -//// [|b|]: number; +//// [|{| "isWriteAccess": true, "isDefinition": true |}b|]: number; //// common: number; ////} //// ////// Assignment ////var v1: A | B = { a: 0, common: "" }; -////var v2: A | B = { [|b|]: 0, common: 3 }; +////var v2: A | B = { [|{| "isWriteAccess": true, "isDefinition": true, "type": "number" |}b|]: 0, common: 3 }; //// ////// Function call ////function consumer(f: A | B) { } -////consumer({ a: 0, [|b|]: 0, common: 1 }); +////consumer({ a: 0, [|{| "isWriteAccess": true, "isDefinition": true, "type": "number" |}b|]: 0, common: 1 }); //// -////// Type cast -////var c = { common: 0, [|b|]: 0 }; +////// Type cast +////var c = { common: 0, [|{| "isWriteAccess": true, "isDefinition": true, "type": "number" |}b|]: 0 }; //// ////// Array literal -////var ar: Array = [{ a: 0, common: "" }, { [|b|]: 0, common: 0 }]; +////var ar: Array = [{ a: 0, common: "" }, { [|{| "isWriteAccess": true, "isDefinition": true, "type": "number" |}b|]: 0, common: 0 }]; //// ////// Nested object literal -////var ob: { aorb: A|B } = { aorb: { [|b|]: 0, common: 0 } }; +////var ob: { aorb: A|B } = { aorb: { [|{| "isWriteAccess": true, "isDefinition": true, "type": "number" |}b|]: 0, common: 0 } }; //// ////// Widened type -////var w: A|B = { [|b|]:undefined, common: undefined }; +////var w: A|B = { [|{| "isWriteAccess": true, "isDefinition": true, "type": "undefined" |}b|]:undefined, common: undefined }; //// ////// Untped -- should not be included ////var u1 = { a: 0, b: 0, common: "" }; ////var u2 = { b: 0, common: 0 }; -verify.rangesReferenceEachOther(); +const ranges = test.ranges(); +verify.referenceGroups(ranges[0], [{ definition: "(property) B.b: number", ranges }]); +for (const reference of ranges.slice(1)) { + const type = reference.marker.data.type; + verify.referenceGroups(reference, [ + { definition: "(property) B.b: number", ranges: ranges.filter(r => r !== reference) }, + { definition: `(property) b: ${type}`, ranges: [reference] } + ]); +} diff --git a/tests/cases/fourslash/referencesForEnums.ts b/tests/cases/fourslash/referencesForEnums.ts index 3b979bc5096..68face36d04 100644 --- a/tests/cases/fourslash/referencesForEnums.ts +++ b/tests/cases/fourslash/referencesForEnums.ts @@ -1,9 +1,9 @@ /// ////enum E { -//// [|value1|] = 1, -//// "[|value2|]" = [|value1|], -//// [|111|] = 11 +//// [|{| "isWriteAccess": true, "isDefinition": true |}value1|] = 1, +//// "[|{| "isDefinition": true |}value2|]" = [|value1|], +//// [|{| "isDefinition": true |}111|] = 11 ////} //// ////E.[|value1|]; @@ -11,4 +11,7 @@ ////E.[|value2|]; ////E[[|111|]]; -verify.rangesWithSameTextReferenceEachOther(); +const r = test.rangesByText(); +verify.singleReferenceGroup("(enum member) E.value1 = 1", r.get("value1")); +verify.singleReferenceGroup("(enum member) E[\"value2\"] = 1", r.get("value2")); +verify.singleReferenceGroup("(enum member) E[111] = 11", r.get("111")); diff --git a/tests/cases/fourslash/referencesForExportedValues.ts b/tests/cases/fourslash/referencesForExportedValues.ts index 315d0b1b585..ff00f844260 100644 --- a/tests/cases/fourslash/referencesForExportedValues.ts +++ b/tests/cases/fourslash/referencesForExportedValues.ts @@ -1,7 +1,7 @@ /// ////module M { -//// export var [|variable|] = 0; +//// export var [|{| "isWriteAccess": true, "isDefinition": true |}variable|] = 0; //// //// // local use //// var x = [|variable|]; @@ -10,4 +10,4 @@ ////// external use ////M.[|variable|] -verify.rangesReferenceEachOther(); +verify.singleReferenceGroup("var M.variable: number"); diff --git a/tests/cases/fourslash/referencesForExternalModuleNames.ts b/tests/cases/fourslash/referencesForExternalModuleNames.ts index ee783c8bd7e..5e01eae3530 100644 --- a/tests/cases/fourslash/referencesForExternalModuleNames.ts +++ b/tests/cases/fourslash/referencesForExternalModuleNames.ts @@ -3,7 +3,7 @@ // Global interface reference. // @Filename: referencesForGlobals_1.ts -////declare module "[|foo|]" { +////declare module "[|{| "isDefinition": true |}foo|]" { //// var f: number; ////} @@ -11,4 +11,7 @@ // @Filename: referencesForGlobals_2.ts ////import f = require("[|foo|]"); -verify.rangesReferenceEachOther(); +const ranges = test.ranges(); +const [r0, r1] = ranges; +verify.referenceGroups(r0, [{ definition: 'module "foo"', ranges }]); +verify.referenceGroups(r1, [{ definition: 'module f', ranges }]); diff --git a/tests/cases/fourslash/referencesForFunctionOverloads.ts b/tests/cases/fourslash/referencesForFunctionOverloads.ts index d6873643cd4..7afa5a20133 100644 --- a/tests/cases/fourslash/referencesForFunctionOverloads.ts +++ b/tests/cases/fourslash/referencesForFunctionOverloads.ts @@ -2,9 +2,9 @@ // Function overloads should be highlighted together. -////function [|foo|](x: string); -////function [|foo|](x: string, y: number) { +////function [|{| "isWriteAccess": true, "isDefinition": true |}foo|](x: string); +////function [|{| "isWriteAccess": true, "isDefinition": true |}foo|](x: string, y: number) { //// [|foo|]('', 43); ////} -verify.rangesReferenceEachOther(); +verify.singleReferenceGroup("function foo(x: string): any"); diff --git a/tests/cases/fourslash/referencesForFunctionParameter.ts b/tests/cases/fourslash/referencesForFunctionParameter.ts index 64d33ca9a60..24582a68e08 100644 --- a/tests/cases/fourslash/referencesForFunctionParameter.ts +++ b/tests/cases/fourslash/referencesForFunctionParameter.ts @@ -3,9 +3,9 @@ ////var x; ////var n; //// -////function n(x: number, [|n|]: number) { -//// [|n|] = 32; +////function n(x: number, [|{| "isWriteAccess": true, "isDefinition": true |}n|]: number) { +//// [|{| "isWriteAccess": true |}n|] = 32; //// x = [|n|]; ////} -verify.rangesReferenceEachOther(); +verify.singleReferenceGroup("(parameter) n: number"); diff --git a/tests/cases/fourslash/referencesForGlobals.ts b/tests/cases/fourslash/referencesForGlobals.ts index f4d7c479767..dc5bc4deb6f 100644 --- a/tests/cases/fourslash/referencesForGlobals.ts +++ b/tests/cases/fourslash/referencesForGlobals.ts @@ -3,7 +3,7 @@ // Global variable reference. // @Filename: referencesForGlobals_1.ts -////var [|global|] = 2; +////var [|{| "isWriteAccess": true, "isDefinition": true |}global|] = 2; //// ////class foo { //// constructor (public global) { } @@ -25,4 +25,4 @@ // @Filename: referencesForGlobals_2.ts ////var m = [|global|]; -verify.rangesReferenceEachOther(); +verify.singleReferenceGroup("var global: number"); diff --git a/tests/cases/fourslash/referencesForGlobals2.ts b/tests/cases/fourslash/referencesForGlobals2.ts index 7c6baf5bf67..e08be585c7a 100644 --- a/tests/cases/fourslash/referencesForGlobals2.ts +++ b/tests/cases/fourslash/referencesForGlobals2.ts @@ -3,11 +3,11 @@ // Global class reference. // @Filename: referencesForGlobals_1.ts -////class [|globalClass|] { +////class [|{| "isWriteAccess": true, "isDefinition": true |}globalClass|] { //// public f() { } ////} // @Filename: referencesForGlobals_2.ts ////var c = [|globalClass|](); -verify.rangesReferenceEachOther(); +verify.singleReferenceGroup("class globalClass"); diff --git a/tests/cases/fourslash/referencesForGlobals3.ts b/tests/cases/fourslash/referencesForGlobals3.ts index 67e209aaad3..38edddc8255 100644 --- a/tests/cases/fourslash/referencesForGlobals3.ts +++ b/tests/cases/fourslash/referencesForGlobals3.ts @@ -3,11 +3,11 @@ // Global interface reference. // @Filename: referencesForGlobals_1.ts -////interface [|globalInterface|] { +////interface [|{| "isWriteAccess": true, "isDefinition": true |}globalInterface|] { //// f(); ////} // @Filename: referencesForGlobals_2.ts ////var i: [|globalInterface|]; -verify.rangesReferenceEachOther(); +verify.singleReferenceGroup("interface globalInterface"); diff --git a/tests/cases/fourslash/referencesForGlobals4.ts b/tests/cases/fourslash/referencesForGlobals4.ts index d7acfbd2df4..b8356461699 100644 --- a/tests/cases/fourslash/referencesForGlobals4.ts +++ b/tests/cases/fourslash/referencesForGlobals4.ts @@ -3,11 +3,11 @@ // Global module reference. // @Filename: referencesForGlobals_1.ts -////module [|globalModule|] { +////module [|{| "isWriteAccess": true, "isDefinition": true |}globalModule|] { //// export f() { }; ////} // @Filename: referencesForGlobals_2.ts ////var m = [|globalModule|]; -verify.rangesReferenceEachOther(); +verify.singleReferenceGroup("namespace globalModule"); diff --git a/tests/cases/fourslash/referencesForGlobals5.ts b/tests/cases/fourslash/referencesForGlobals5.ts index 4db2410f638..d7dd9304746 100644 --- a/tests/cases/fourslash/referencesForGlobals5.ts +++ b/tests/cases/fourslash/referencesForGlobals5.ts @@ -7,9 +7,9 @@ //// export var x; ////} //// -////import [|globalAlias|] = globalModule; +////import [|{| "isWriteAccess": true, "isDefinition": true |}globalAlias|] = globalModule; // @Filename: referencesForGlobals_2.ts ////var m = [|globalAlias|]; -verify.rangesReferenceEachOther(); +verify.singleReferenceGroup("import globalAlias = globalModule"); diff --git a/tests/cases/fourslash/referencesForGlobalsInExternalModule.ts b/tests/cases/fourslash/referencesForGlobalsInExternalModule.ts index c2f70420402..5047a2f12a4 100644 --- a/tests/cases/fourslash/referencesForGlobalsInExternalModule.ts +++ b/tests/cases/fourslash/referencesForGlobalsInExternalModule.ts @@ -2,20 +2,28 @@ // Global variable reference. -////var [|topLevelVar|] = 2; +////var [|{| "isWriteAccess": true, "isDefinition": true |}topLevelVar|] = 2; ////var topLevelVar2 = [|topLevelVar|]; //// -////class [|topLevelClass|] { } +////class [|{| "isWriteAccess": true, "isDefinition": true |}topLevelClass|] { } ////var c = new [|topLevelClass|](); //// -////interface [|topLevelInterface|] { } +////interface [|{| "isWriteAccess": true, "isDefinition": true |}topLevelInterface|] { } ////var i: [|topLevelInterface|]; //// -////module [|topLevelModule|] { +////module [|{| "isWriteAccess": true, "isDefinition": true |}topLevelModule|] { //// export var x; ////} ////var x = [|topLevelModule|].x; //// ////export = x; -verify.rangesWithSameTextReferenceEachOther(); +const ranges = test.rangesByText(); +verify.singleReferenceGroup("var topLevelVar: number", ranges.get("topLevelVar")); + +const topLevelClass = ranges.get("topLevelClass"); +verify.referenceGroups(topLevelClass[0], [{ definition: "class topLevelClass", ranges: topLevelClass }]); +verify.referenceGroups(topLevelClass[1], [{ definition: "constructor topLevelClass(): topLevelClass", ranges: topLevelClass }]); + +verify.singleReferenceGroup("interface topLevelInterface", ranges.get("topLevelInterface")); +verify.singleReferenceGroup("namespace topLevelModule", ranges.get("topLevelModule")); diff --git a/tests/cases/fourslash/referencesForIllegalAssignment.ts b/tests/cases/fourslash/referencesForIllegalAssignment.ts index 59cb6f4f273..f65cd5bf1a6 100644 --- a/tests/cases/fourslash/referencesForIllegalAssignment.ts +++ b/tests/cases/fourslash/referencesForIllegalAssignment.ts @@ -2,13 +2,13 @@ ////f/*1*/oo = fo/*2*/o; -////var [|bar|] = function () { }; -////[|bar|] = [|bar|] + 1; +////var [|{| "isWriteAccess": true, "isDefinition": true |}bar|] = function () { }; +////[|{| "isWriteAccess": true |}bar|] = [|bar|] + 1; goTo.marker("1"); -verify.referencesAre([]); +verify.noReferences(); goTo.marker("2"); -verify.referencesAre([]); +verify.noReferences(); -verify.rangesReferenceEachOther(); +verify.singleReferenceGroup("var bar: () => void"); diff --git a/tests/cases/fourslash/referencesForImports.ts b/tests/cases/fourslash/referencesForImports.ts index 0203bcee096..54cbb0f1155 100644 --- a/tests/cases/fourslash/referencesForImports.ts +++ b/tests/cases/fourslash/referencesForImports.ts @@ -5,11 +5,11 @@ //// export = $; ////} -////import [|$|] = require("jquery"); +////import [|{| "isWriteAccess": true, "isDefinition": true |}$|] = require("jquery"); ////[|$|]("a"); -////import [|$|] = require("jquery"); +////import [|{| "isWriteAccess": true, "isDefinition": true |}$|] = require("jquery"); const [r0, r1, r2] = test.ranges(); -verify.rangesReferenceEachOther([r0, r1]); -verify.referencesOf(r2, [r2]); +verify.singleReferenceGroup('import $ = require("jquery")', [r0, r1]); +verify.singleReferenceGroup('import $ = require("jquery")', [r2]); diff --git a/tests/cases/fourslash/referencesForIndexProperty.ts b/tests/cases/fourslash/referencesForIndexProperty.ts index 49d12c25819..dba2549e414 100644 --- a/tests/cases/fourslash/referencesForIndexProperty.ts +++ b/tests/cases/fourslash/referencesForIndexProperty.ts @@ -3,12 +3,14 @@ // References a class property using string index access ////class Foo { -//// [|property|]: number; -//// [|method|](): void { } +//// [|{| "isWriteAccess": true, "isDefinition": true |}property|]: number; +//// [|{| "isWriteAccess": true, "isDefinition": true |}method|](): void { } ////} //// ////var f: Foo; ////f["[|property|]"]; ////f["[|method|]"]; -verify.rangesWithSameTextReferenceEachOther(); +const ranges = test.rangesByText(); +verify.singleReferenceGroup("(property) Foo.property: number", ranges.get("property")); +verify.singleReferenceGroup("(method) Foo.method(): void", ranges.get("method")); diff --git a/tests/cases/fourslash/referencesForIndexProperty2.ts b/tests/cases/fourslash/referencesForIndexProperty2.ts index 35c9d7cdd64..a4d5c75a908 100644 --- a/tests/cases/fourslash/referencesForIndexProperty2.ts +++ b/tests/cases/fourslash/referencesForIndexProperty2.ts @@ -5,4 +5,4 @@ ////var a; ////a["[|blah|]"]; -verify.rangesReferenceEachOther(); +verify.singleReferenceGroup('"blah"'); diff --git a/tests/cases/fourslash/referencesForIndexProperty3.ts b/tests/cases/fourslash/referencesForIndexProperty3.ts index 1fdee9b6602..a2e008c937e 100644 --- a/tests/cases/fourslash/referencesForIndexProperty3.ts +++ b/tests/cases/fourslash/referencesForIndexProperty3.ts @@ -3,7 +3,7 @@ // References to a property of the apparent type using string indexer ////interface Object { -//// [|toMyString|](); +//// [|{| "isWriteAccess": true, "isDefinition": true |}toMyString|](); ////} //// ////var y: Object; @@ -12,4 +12,4 @@ ////var x = {}; ////x["[|toMyString|]"](); -verify.rangesReferenceEachOther(); +verify.singleReferenceGroup("(method) Object.toMyString(): any"); diff --git a/tests/cases/fourslash/referencesForInheritedProperties.ts b/tests/cases/fourslash/referencesForInheritedProperties.ts index 19fef4066ee..c2674fe1fe1 100644 --- a/tests/cases/fourslash/referencesForInheritedProperties.ts +++ b/tests/cases/fourslash/referencesForInheritedProperties.ts @@ -1,15 +1,15 @@ /// ////interface interface1 { -//// [|doStuff|](): void; +//// [|{| "isWriteAccess": true, "isDefinition": true |}doStuff|](): void; ////} //// ////interface interface2 extends interface1{ -//// [|doStuff|](): void; +//// [|{| "isWriteAccess": true, "isDefinition": true |}doStuff|](): void; ////} //// ////class class1 implements interface2 { -//// [|doStuff|]() { +//// [|{| "isWriteAccess": true, "isDefinition": true |}doStuff|]() { //// //// } ////} @@ -21,4 +21,21 @@ ////var v: class2; ////v.[|doStuff|](); -verify.rangesWithSameTextReferenceEachOther(); +const ranges = test.ranges(); +const [r0, r1, r2, r3] = ranges; +verify.referenceGroups(r0, [{ definition: "(method) interface1.doStuff(): void", ranges }]); +verify.referenceGroups(r1, [ + { definition: "(method) interface1.doStuff(): void", ranges: [r0] }, + { definition: "(method) interface2.doStuff(): void", ranges: [r1, r2, r3] } +]); +verify.referenceGroups(r2, [ + { definition: "(method) interface1.doStuff(): void", ranges: [r0] }, + { definition: "(method) interface2.doStuff(): void", ranges: [r1] }, + { definition: "(method) class1.doStuff(): void", ranges: [r2, r3] } +]); +verify.referenceGroups(r3, [ + { definition: "(method) interface1.doStuff(): void", ranges: [r0] }, + { definition: "(method) interface2.doStuff(): void", ranges: [r1] }, + { definition: "(method) class1.doStuff(): void", ranges: [r2] }, + { definition: "(method) class1.doStuff(): void", ranges: [r3] } +]); diff --git a/tests/cases/fourslash/referencesForInheritedProperties2.ts b/tests/cases/fourslash/referencesForInheritedProperties2.ts index 33a7f26aaea..0f89a9aa744 100644 --- a/tests/cases/fourslash/referencesForInheritedProperties2.ts +++ b/tests/cases/fourslash/referencesForInheritedProperties2.ts @@ -3,18 +3,18 @@ // extends statement in a diffrent declaration ////interface interface1 { -//// [|doStuff|](): void; +//// [|{| "isWriteAccess": true, "isDefinition": true |}doStuff|](): void; ////} //// ////interface interface2 { -//// [|doStuff|](): void; +//// [|{| "isWriteAccess": true, "isDefinition": true |}doStuff|](): void; ////} //// ////interface interface2 extends interface1 { ////} //// ////class class1 implements interface2 { -//// [|doStuff|]() { +//// [|{| "isWriteAccess": true, "isDefinition": true |}doStuff|]() { //// //// } ////} @@ -26,4 +26,21 @@ ////var v: class2; ////v.[|doStuff|](); -verify.rangesReferenceEachOther(); +const ranges = test.ranges(); +const [r0, r1, r2, r3] = ranges; +verify.referenceGroups(r0, [{ definition: "(method) interface1.doStuff(): void", ranges }]); +verify.referenceGroups(r1, [ + { definition: "(method) interface1.doStuff(): void", ranges: [r0] }, + { definition: "(method) interface2.doStuff(): void", ranges: [r1, r2, r3] } +]); +verify.referenceGroups(r2, [ + { definition: "(method) interface1.doStuff(): void", ranges: [r0] }, + { definition: "(method) interface2.doStuff(): void", ranges: [r1] }, + { definition: "(method) class1.doStuff(): void", ranges: [r2, r3] } +]); +verify.referenceGroups(r3, [ + { definition: "(method) interface1.doStuff(): void", ranges: [r0] }, + { definition: "(method) interface2.doStuff(): void", ranges: [r1] }, + { definition: "(method) class1.doStuff(): void", ranges: [r2] }, + { definition: "(method) class1.doStuff(): void", ranges: [r3] } +]); diff --git a/tests/cases/fourslash/referencesForInheritedProperties3.ts b/tests/cases/fourslash/referencesForInheritedProperties3.ts index 3a2d11da692..c6c870ca350 100644 --- a/tests/cases/fourslash/referencesForInheritedProperties3.ts +++ b/tests/cases/fourslash/referencesForInheritedProperties3.ts @@ -1,12 +1,14 @@ /// //// interface interface1 extends interface1 { -//// [|doStuff|](): void; -//// [|propName|]: string; +//// [|{| "isWriteAccess": true, "isDefinition": true |}doStuff|](): void; +//// [|{| "isWriteAccess": true, "isDefinition": true |}propName|]: string; //// } //// //// var v: interface1; //// v.[|propName|]; //// v.[|doStuff|](); -verify.rangesWithSameTextReferenceEachOther(); +const ranges = test.rangesByText(); +verify.singleReferenceGroup("(method) interface1.doStuff(): void", ranges.get("doStuff")); +verify.singleReferenceGroup("(property) interface1.propName: string", ranges.get("propName")); diff --git a/tests/cases/fourslash/referencesForInheritedProperties4.ts b/tests/cases/fourslash/referencesForInheritedProperties4.ts index 96010d05086..8a822ec5238 100644 --- a/tests/cases/fourslash/referencesForInheritedProperties4.ts +++ b/tests/cases/fourslash/referencesForInheritedProperties4.ts @@ -1,12 +1,21 @@ /// //// class class1 extends class1 { -//// [|doStuff|]() { } -//// [|propName|]: string; +//// [|{| "isWriteAccess": true, "isDefinition": true |}doStuff|]() { } +//// [|{| "isWriteAccess": true, "isDefinition": true |}propName|]: string; //// } //// //// var c: class1; //// c.[|doStuff|](); //// c.[|propName|]; -verify.rangesWithSameTextReferenceEachOther(); +const ranges = test.rangesByText(); +const [r0, r1] = ranges.get("doStuff"); +verify.referenceGroups(r0, [ + { definition: "(method) class1.doStuff(): void", ranges: [r0, r1] }, +]); +verify.referenceGroups(r1, [ + { definition: "(method) class1.doStuff(): void", ranges: [r0] }, + { definition: "(method) class1.doStuff(): void", ranges: [r1] }, +]); +verify.singleReferenceGroup("(property) class1.propName: string", ranges.get("propName")); diff --git a/tests/cases/fourslash/referencesForInheritedProperties5.ts b/tests/cases/fourslash/referencesForInheritedProperties5.ts index bbb86f0defb..7a5cff0ad2b 100644 --- a/tests/cases/fourslash/referencesForInheritedProperties5.ts +++ b/tests/cases/fourslash/referencesForInheritedProperties5.ts @@ -1,16 +1,28 @@ /// //// interface interface1 extends interface1 { -//// [|doStuff|](): void; -//// [|propName|]: string; +//// [|{| "isWriteAccess": true, "isDefinition": true |}doStuff|](): void; +//// [|{| "isWriteAccess": true, "isDefinition": true |}propName|]: string; //// } //// interface interface2 extends interface1 { -//// [|doStuff|](): void; -//// [|propName|]: string; +//// [|{| "isWriteAccess": true, "isDefinition": true |}doStuff|](): void; +//// [|{| "isWriteAccess": true, "isDefinition": true |}propName|]: string; //// } //// //// var v: interface1; //// v.[|propName|]; //// v.[|doStuff|](); -verify.rangesWithSameTextReferenceEachOther(); +const ranges = test.rangesByText(); +const [m0, m1, m2] = ranges.get("doStuff"); +const [p0, p1, p2] = ranges.get("propName"); +verify.referenceGroups([m0, m2], [{ definition: "(method) interface1.doStuff(): void", ranges: [m0, m1, m2] }]); +verify.referenceGroups(m1, [ + { definition: "(method) interface1.doStuff(): void", ranges: [m0, m2] }, + { definition: "(method) interface2.doStuff(): void", ranges: [m1] } +]); +verify.referenceGroups([p0, p2], [{ definition: "(property) interface1.propName: string", ranges: [p0, p1, p2] }]); +verify.referenceGroups(p1, [ + { definition: "(property) interface1.propName: string", ranges: [p0, p2] }, + { definition: "(property) interface2.propName: string", ranges: [p1] } +]); diff --git a/tests/cases/fourslash/referencesForInheritedProperties6.ts b/tests/cases/fourslash/referencesForInheritedProperties6.ts index ff008cceb43..a39dc085c71 100644 --- a/tests/cases/fourslash/referencesForInheritedProperties6.ts +++ b/tests/cases/fourslash/referencesForInheritedProperties6.ts @@ -1,16 +1,27 @@ /// //// class class1 extends class1 { -//// [|doStuff|]() { } -//// [|propName|]: string; +//// [|{| "isWriteAccess": true, "isDefinition": true |}doStuff|]() { } +//// [|{| "isWriteAccess": true, "isDefinition": true |}propName|]: string; //// } //// class class2 extends class1 { -//// [|doStuff|]() { } -//// [|propName|]: string; +//// [|{| "isWriteAccess": true, "isDefinition": true |}doStuff|]() { } +//// [|{| "isWriteAccess": true, "isDefinition": true |}propName|]: string; //// } //// //// var v: class2; //// v.[|propName|]; //// v.[|doStuff|](); -verify.rangesWithSameTextReferenceEachOther(); +const ranges = test.rangesByText(); +const [m0, m1, m2] = ranges.get("doStuff"); +verify.referenceGroups(m0, [{ definition: "(method) class1.doStuff(): void", ranges: [m0, m1, m2] }]); +verify.referenceGroups(m1, [ + { definition: "(method) class1.doStuff(): void", ranges: [m0] }, + { definition: "(method) class2.doStuff(): void", ranges: [m1, m2] } +]); +verify.referenceGroups(m2, [ + { definition: "(method) class1.doStuff(): void", ranges: [m0] }, + { definition: "(method) class2.doStuff(): void", ranges: [m1] }, + { definition: "(method) class2.doStuff(): void", ranges: [m2] } +]); diff --git a/tests/cases/fourslash/referencesForInheritedProperties7.ts b/tests/cases/fourslash/referencesForInheritedProperties7.ts index ec92a06f0a3..4911cbefd57 100644 --- a/tests/cases/fourslash/referencesForInheritedProperties7.ts +++ b/tests/cases/fourslash/referencesForInheritedProperties7.ts @@ -1,30 +1,40 @@ /// //// class class1 extends class1 { -//// [|doStuff|]() { } -//// [|propName|]: string; +//// [|{| "isWriteAccess": true, "isDefinition": true |}doStuff|]() { } +//// [|{| "isWriteAccess": true, "isDefinition": true |}propName|]: string; //// } //// interface interface1 extends interface1 { -//// [|doStuff|](): void; -//// [|propName|]: string; +//// [|{| "isWriteAccess": true, "isDefinition": true |}doStuff|](): void; +//// [|{| "isWriteAccess": true, "isDefinition": true |}propName|]: string; //// } //// class class2 extends class1 implements interface1 { -//// [|doStuff|]() { } -//// [|propName|]: string; +//// [|{| "isWriteAccess": true, "isDefinition": true |}doStuff|]() { } +//// [|{| "isWriteAccess": true, "isDefinition": true |}propName|]: string; //// } //// //// var v: class2; -//// v.[|propName|]; //// v.[|doStuff|](); +//// v.[|propName|]; const [r0, r1, r2, r3, r4, r5, r6, r7] = test.ranges(); -verify.referencesOf(r0, [r0, r4, r7]); -verify.referencesOf(r1, [r1, r5, r6]); -verify.referencesOf(r2, [r2, r4, r7]); -verify.referencesOf(r3, [r3, r5, r6]); -const allDoStuff = [r0, r2, r4, r7]; -verify.referencesOf(r4, allDoStuff); -const allPropName = [r1, r3, r5, r6]; -verify.referencesOf(r5, allPropName); -verify.referencesOf(r6, allPropName); -verify.referencesOf(r7, allDoStuff); +verify.referenceGroups(r0, [{ definition: "(method) class1.doStuff(): void", ranges: [r0, r4, r6] }]); +verify.referenceGroups(r1, [{ definition: "(property) class1.propName: string", ranges: [r1, r5, r7] }]); +verify.referenceGroups(r2, [{ definition: "(method) interface1.doStuff(): void", ranges: [r2, r4, r6] }]); +verify.referenceGroups(r3, [{ definition: "(property) interface1.propName: string", ranges: [r3, r5, r7] }]); +verify.referenceGroups(r4, [ + { definition: "(method) class1.doStuff(): void", ranges: [r0] }, + { definition: "(method) interface1.doStuff(): void", ranges: [r2] }, + { definition: "(method) class2.doStuff(): void", ranges: [r4, r6] } +]); +verify.referenceGroups([r5, r7], [ + { definition: "(property) class1.propName: string", ranges: [r1] }, + { definition: "(property) interface1.propName: string", ranges: [r3] }, + { definition: "(property) class2.propName: string", ranges: [r5, r7] } +]); +verify.referenceGroups(r6, [ + { definition: "(method) class1.doStuff(): void", ranges: [r0] }, + { definition: "(method) interface1.doStuff(): void", ranges: [r2] }, + { definition: "(method) class2.doStuff(): void", ranges: [r4] }, + { definition: "(method) class2.doStuff(): void", ranges: [r6] } +]); diff --git a/tests/cases/fourslash/referencesForInheritedProperties8.ts b/tests/cases/fourslash/referencesForInheritedProperties8.ts index 964309fc477..d0d94b49b57 100644 --- a/tests/cases/fourslash/referencesForInheritedProperties8.ts +++ b/tests/cases/fourslash/referencesForInheritedProperties8.ts @@ -1,16 +1,19 @@ /// //// interface C extends D { -//// [|propD|]: number; +//// [|{| "isWriteAccess": true, "isDefinition": true |}propD|]: number; //// } //// interface D extends C { -//// [|propD|]: string; -//// [|propC|]: number; +//// [|{| "isWriteAccess": true, "isDefinition": true |}propD|]: string; +//// [|{| "isWriteAccess": true, "isDefinition": true |}propC|]: number; //// } //// var d: D; //// d.[|propD|]; //// d.[|propC|]; const [d0, d1, c0, d2, c1] = test.ranges(); -verify.rangesReferenceEachOther([d0, d1, d2]); -verify.rangesReferenceEachOther([c0, c1]); +verify.referenceGroups([d0, d1, d2], [ + { definition: "(property) C.propD: number", ranges: [d0] }, + { definition: "(property) D.propD: string", ranges: [d1, d2] }, +]); +verify.singleReferenceGroup("(property) D.propC: number", [c0, c1]); diff --git a/tests/cases/fourslash/referencesForInheritedProperties9.ts b/tests/cases/fourslash/referencesForInheritedProperties9.ts index 7d4330d0aa6..27bc164a8fc 100644 --- a/tests/cases/fourslash/referencesForInheritedProperties9.ts +++ b/tests/cases/fourslash/referencesForInheritedProperties9.ts @@ -1,16 +1,16 @@ /// //// class D extends C { -//// [|prop1|]: string; +//// [|{| "isWriteAccess": true, "isDefinition": true |}prop1|]: string; //// } -//// +//// //// class C extends D { -//// [|prop1|]: string; +//// [|{| "isWriteAccess": true, "isDefinition": true |}prop1|]: string; //// } -//// +//// //// var c: C; //// c.[|prop1|]; const [r0, r1, r2] = test.ranges(); -verify.referencesOf(r0, [r0]); -verify.rangesReferenceEachOther([r1, r2]); +verify.singleReferenceGroup("(property) D.prop1: string", [r0]); +verify.singleReferenceGroup("(property) C.prop1: string", [r1, r2]); diff --git a/tests/cases/fourslash/referencesForLabel.ts b/tests/cases/fourslash/referencesForLabel.ts index 14b58fd1d92..1abcafda0f2 100644 --- a/tests/cases/fourslash/referencesForLabel.ts +++ b/tests/cases/fourslash/referencesForLabel.ts @@ -11,5 +11,5 @@ ////var label = "label"; const [r0, r1, r2, r3] = test.ranges(); -verify.rangesReferenceEachOther([r0, r1, r2]); -verify.referencesOf(r3, [r3]); +verify.singleReferenceGroup("label", [r0, r1, r2]); +verify.singleReferenceGroup("label", [r3]); diff --git a/tests/cases/fourslash/referencesForLabel2.ts b/tests/cases/fourslash/referencesForLabel2.ts index 841e35ad700..6f3721431e0 100644 --- a/tests/cases/fourslash/referencesForLabel2.ts +++ b/tests/cases/fourslash/referencesForLabel2.ts @@ -8,5 +8,4 @@ //// if (true) continue label; ////} -goTo.marker(); -verify.referencesAre([]); +verify.noReferences(""); diff --git a/tests/cases/fourslash/referencesForLabel3.ts b/tests/cases/fourslash/referencesForLabel3.ts index fb7a51f858e..13622eb90c3 100644 --- a/tests/cases/fourslash/referencesForLabel3.ts +++ b/tests/cases/fourslash/referencesForLabel3.ts @@ -6,5 +6,4 @@ //// var label = "label"; ////} -const [label] = test.ranges(); -verify.referencesOf(label, [label]); +verify.singleReferenceGroup("label"); diff --git a/tests/cases/fourslash/referencesForLabel4.ts b/tests/cases/fourslash/referencesForLabel4.ts index 5462500f53c..2ff159bc755 100644 --- a/tests/cases/fourslash/referencesForLabel4.ts +++ b/tests/cases/fourslash/referencesForLabel4.ts @@ -8,4 +8,4 @@ //// } ////} -verify.rangesReferenceEachOther(); +verify.singleReferenceGroup("label"); diff --git a/tests/cases/fourslash/referencesForLabel5.ts b/tests/cases/fourslash/referencesForLabel5.ts index 48d5aab04c2..bc986e3350d 100644 --- a/tests/cases/fourslash/referencesForLabel5.ts +++ b/tests/cases/fourslash/referencesForLabel5.ts @@ -13,5 +13,5 @@ //// } const [outer1, outer2, inner1, inner2, outer3] = test.ranges(); -verify.rangesReferenceEachOther([outer1, outer2, outer3]); -verify.rangesReferenceEachOther([inner1, inner2]); +verify.singleReferenceGroup("label", [outer1, outer2, outer3]); +verify.singleReferenceGroup("label", [inner1, inner2]); diff --git a/tests/cases/fourslash/referencesForLabel6.ts b/tests/cases/fourslash/referencesForLabel6.ts index aea45805756..0255c07943c 100644 --- a/tests/cases/fourslash/referencesForLabel6.ts +++ b/tests/cases/fourslash/referencesForLabel6.ts @@ -7,6 +7,6 @@ //// break labelc; ////} -const [a, b, useB] = test.ranges(); -verify.referencesOf(a, [a]); -verify.rangesReferenceEachOther([b, useB]); +const ranges = test.rangesByText(); +verify.singleReferenceGroup("labela", ranges.get("labela")); +verify.singleReferenceGroup("labelb", ranges.get("labelb")); diff --git a/tests/cases/fourslash/referencesForMergedDeclarations.ts b/tests/cases/fourslash/referencesForMergedDeclarations.ts index 8a0a5d4c680..3e2fe8e4b2c 100644 --- a/tests/cases/fourslash/referencesForMergedDeclarations.ts +++ b/tests/cases/fourslash/referencesForMergedDeclarations.ts @@ -1,13 +1,13 @@ /// -////interface [|Foo|] { +////interface [|{| "isWriteAccess": true, "isDefinition": true |}Foo|] { ////} //// -////module [|Foo|] { +////module [|{| "isWriteAccess": true, "isDefinition": true |}Foo|] { //// export interface Bar { } ////} //// -////function [|Foo|](): void { +////function [|{| "isWriteAccess": true, "isDefinition": true |}Foo|](): void { ////} //// ////var f1: [|Foo|].Bar; @@ -15,6 +15,7 @@ ////[|Foo|].bind(this); const [type1, namespace1, value1, namespace2, type2, value2] = test.ranges(); -verify.rangesReferenceEachOther([type1, type2]); -verify.rangesReferenceEachOther([namespace1, namespace2]); -verify.rangesReferenceEachOther([value1, value2]); +verify.singleReferenceGroup("interface Foo\nnamespace Foo\nfunction Foo(): void", [type1, type2]); +verify.singleReferenceGroup("namespace Foo\nfunction Foo(): void", [namespace1, namespace2]); +verify.referenceGroups(value1, [{ definition: "function Foo(): void\nnamespace Foo", ranges: [value1, value2] }]); +verify.referenceGroups(value2, [{ definition: "namespace Foo\nfunction Foo(): void", ranges: [value1, value2] }]); diff --git a/tests/cases/fourslash/referencesForMergedDeclarations2.ts b/tests/cases/fourslash/referencesForMergedDeclarations2.ts index 75d485002a4..5cf9234511a 100644 --- a/tests/cases/fourslash/referencesForMergedDeclarations2.ts +++ b/tests/cases/fourslash/referencesForMergedDeclarations2.ts @@ -6,9 +6,9 @@ //// ////function ATest() { } //// -////import [|alias|] = ATest; // definition +////import [|{| "isWriteAccess": true, "isDefinition": true |}alias|] = ATest; // definition //// ////var a: [|alias|].Bar; // namespace ////[|alias|].call(this); // value -verify.rangesReferenceEachOther(); +verify.singleReferenceGroup("import alias = ATest"); diff --git a/tests/cases/fourslash/referencesForMergedDeclarations3.ts b/tests/cases/fourslash/referencesForMergedDeclarations3.ts index 181d68e79b3..5ce024258ed 100644 --- a/tests/cases/fourslash/referencesForMergedDeclarations3.ts +++ b/tests/cases/fourslash/referencesForMergedDeclarations3.ts @@ -1,13 +1,13 @@ /// -// class and uninstanciated module +// class and uninstantiated module -////class [|testClass|] { +////class [|{| "isWriteAccess": true, "isDefinition": true |}testClass|] { //// static staticMethod() { } //// method() { } ////} //// -////module [|testClass|] { +////module [|{| "isWriteAccess": true, "isDefinition": true |}testClass|] { //// export interface Bar { //// //// } @@ -21,5 +21,7 @@ ////new [|testClass|](); const [class0, module0, class1, module1, class2, class3, class4, class5] = test.ranges(); -verify.rangesReferenceEachOther([module0, module1]); -verify.rangesReferenceEachOther([class0, class1, class2, class3, class4, class5]); +verify.singleReferenceGroup("class testClass\nnamespace testClass", [module0, module1]); +const classes = [class0, class1, class2, class3, class4, class5]; +verify.referenceGroups(classes.slice(0, 5), [{ definition: "class testClass\nnamespace testClass", ranges: classes }]); +verify.referenceGroups(class5, [{ definition: "constructor testClass(): testClass\nnamespace testClass", ranges: classes }]); diff --git a/tests/cases/fourslash/referencesForMergedDeclarations4.ts b/tests/cases/fourslash/referencesForMergedDeclarations4.ts index d35cbea745d..55eb331dd90 100644 --- a/tests/cases/fourslash/referencesForMergedDeclarations4.ts +++ b/tests/cases/fourslash/referencesForMergedDeclarations4.ts @@ -1,13 +1,13 @@ /// -// class and instanciated module +// class and instantiated module -////class [|testClass|] { +////class [|{| "isWriteAccess": true, "isDefinition": true |}testClass|] { //// static staticMethod() { } //// method() { } ////} //// -////module [|testClass|] { +////module [|{| "isWriteAccess": true, "isDefinition": true |}testClass|] { //// export interface Bar { //// //// } @@ -22,4 +22,6 @@ ////[|testClass|].s; ////new [|testClass|](); -verify.rangesReferenceEachOther(); +const ranges = test.ranges(); +verify.referenceGroups(ranges.slice(0, 8), [{ definition: "class testClass\nnamespace testClass", ranges }]); +verify.referenceGroups(ranges[8], [{ definition: "constructor testClass(): testClass\nnamespace testClass", ranges }]); diff --git a/tests/cases/fourslash/referencesForMergedDeclarations5.ts b/tests/cases/fourslash/referencesForMergedDeclarations5.ts index 8fe33ca31e4..8cf597333b0 100644 --- a/tests/cases/fourslash/referencesForMergedDeclarations5.ts +++ b/tests/cases/fourslash/referencesForMergedDeclarations5.ts @@ -1,10 +1,14 @@ /// -////interface [|Foo|] { } -////module [|Foo|] { export interface Bar { } } -////function [|Foo|]() { } +////interface [|{| "isWriteAccess": true, "isDefinition": true |}Foo|] { } +////module [|{| "isWriteAccess": true, "isDefinition": true |}Foo|] { export interface Bar { } } +////function [|{| "isWriteAccess": true, "isDefinition": true |}Foo|]() { } //// ////export = [|Foo|]; -const [r0, r1, r2, r3] = test.ranges(); -verify.referencesOf(r3, [r0, r1, r2, r3]); +const ranges = test.ranges(); +const [r0, r1, r2, r3] = ranges; +verify.referenceGroups(r0, [{ definition: "interface Foo\nnamespace Foo\nfunction Foo(): void", ranges: [r0, r3] }]); +verify.referenceGroups(r1, [{ definition: "namespace Foo\nfunction Foo(): void", ranges: [r1, r3] }]); +verify.referenceGroups(r2, [{ definition: "function Foo(): void\nnamespace Foo", ranges: [r2, r3] }]); +verify.referenceGroups(r3, [{ definition: "interface Foo\nnamespace Foo\nfunction Foo(): void", ranges }]); diff --git a/tests/cases/fourslash/referencesForMergedDeclarations6.ts b/tests/cases/fourslash/referencesForMergedDeclarations6.ts index e4b5b9111c6..79ee0128ab6 100644 --- a/tests/cases/fourslash/referencesForMergedDeclarations6.ts +++ b/tests/cases/fourslash/referencesForMergedDeclarations6.ts @@ -1,7 +1,7 @@ /// ////interface Foo { } -////module [|Foo|] { +////module [|{| "isWriteAccess": true, "isDefinition": true |}Foo|] { //// export interface Bar { } //// export module Bar { export interface Baz { } } //// export function Bar() { } @@ -10,4 +10,4 @@ ////// module ////import a1 = [|Foo|]; -verify.rangesReferenceEachOther(); +verify.singleReferenceGroup("namespace Foo"); diff --git a/tests/cases/fourslash/referencesForMergedDeclarations7.ts b/tests/cases/fourslash/referencesForMergedDeclarations7.ts index bc56b5d6f9d..66acffde980 100644 --- a/tests/cases/fourslash/referencesForMergedDeclarations7.ts +++ b/tests/cases/fourslash/referencesForMergedDeclarations7.ts @@ -2,13 +2,17 @@ ////interface Foo { } ////module Foo { -//// export interface [|Bar|] { } -//// export module [|Bar|] { export interface Baz { } } -//// export function [|Bar|]() { } +//// export interface [|{| "isWriteAccess": true, "isDefinition": true |}Bar|] { } +//// export module [|{| "isWriteAccess": true, "isDefinition": true |}Bar|] { export interface Baz { } } +//// export function [|{| "isWriteAccess": true, "isDefinition": true |}Bar|]() { } ////} //// ////// module, value and type ////import a2 = Foo.[|Bar|]; -const [r0, r1, r2, r3] = test.ranges(); -verify.referencesOf(r3, [r0, r1, r2, r3]); +const ranges = test.ranges(); +const [r0, r1, r2, r3] = ranges; +verify.referenceGroups(r0, [{ definition: "interface Foo.Bar\nnamespace Foo.Bar\nfunction Foo.Bar(): void", ranges: [r0, r3] }]); +verify.referenceGroups(r1, [{ definition: "namespace Foo.Bar\nfunction Foo.Bar(): void", ranges: [r1, r3] }]); +verify.referenceGroups(r2, [{ definition: "function Foo.Bar(): void\nnamespace Foo.Bar", ranges: [r2, r3] }]); +verify.referenceGroups(r3, [{ definition: "interface Foo.Bar\nnamespace Foo.Bar\nfunction Foo.Bar(): void", ranges }]); diff --git a/tests/cases/fourslash/referencesForMergedDeclarations8.ts b/tests/cases/fourslash/referencesForMergedDeclarations8.ts index b5b1428b7c9..742561e21c5 100644 --- a/tests/cases/fourslash/referencesForMergedDeclarations8.ts +++ b/tests/cases/fourslash/referencesForMergedDeclarations8.ts @@ -3,11 +3,11 @@ ////interface Foo { } ////module Foo { //// export interface Bar { } -//// export module [|Bar|] { export interface Baz { } } +//// export module [|{| "isWriteAccess": true, "isDefinition": true |}Bar|] { export interface Baz { } } //// export function Bar() { } ////} //// ////// module ////import a3 = Foo.[|Bar|].Baz; -verify.rangesReferenceEachOther(); +verify.singleReferenceGroup("namespace Foo.Bar\nfunction Foo.Bar(): void"); diff --git a/tests/cases/fourslash/referencesForNoContext.ts b/tests/cases/fourslash/referencesForNoContext.ts index 4631ce50c16..2ea57656167 100644 --- a/tests/cases/fourslash/referencesForNoContext.ts +++ b/tests/cases/fourslash/referencesForNoContext.ts @@ -21,14 +21,4 @@ //// } ////} -goTo.marker("1"); -verify.referencesAre([]); - -goTo.marker("2"); -verify.referencesAre([]); - -goTo.marker("3"); -verify.referencesAre([]); - -goTo.marker("4"); -verify.referencesAre([]); +goTo.eachMarker(() => verify.noReferences()); diff --git a/tests/cases/fourslash/referencesForNumericLiteralPropertyNames.ts b/tests/cases/fourslash/referencesForNumericLiteralPropertyNames.ts index 5e6e8172092..effa4abc164 100644 --- a/tests/cases/fourslash/referencesForNumericLiteralPropertyNames.ts +++ b/tests/cases/fourslash/referencesForNumericLiteralPropertyNames.ts @@ -1,12 +1,23 @@ /// ////class Foo { -//// public [|12|]: any; +//// public [|{| "isDefinition": true |}12|]: any; ////} //// ////var x: Foo; ////x[[|12|]]; -////x = { "[|12|]": 0 }; -////x = { [|12|]: 0 }; +////x = { "[|{| "isDefinition": true |}12|]": 0 }; +////x = { [|{| "isDefinition": true |}12|]: 0 }; -verify.rangesReferenceEachOther(); +//verify.singleReferenceGroup("(property) Foo[12]: any"); +const ranges = test.ranges(); +const [r0, r1, r2, r3] = ranges; +verify.referenceGroups([r0, r1], [{ definition: "(property) Foo[12]: any", ranges }]); +verify.referenceGroups(r2, [ + { definition: "(property) Foo[12]: any", ranges: [r0, r1, r3] }, + { definition: "(property) \"12\": number", ranges: [r2] } +]); +verify.referenceGroups(r3, [ + { definition: "(property) Foo[12]: any", ranges: [r0, r1, r2] }, + { definition: "(property) 12: number", ranges: [r3] } +]); diff --git a/tests/cases/fourslash/referencesForObjectLiteralProperties.ts b/tests/cases/fourslash/referencesForObjectLiteralProperties.ts index f2a815e845b..ea7c20829ae 100644 --- a/tests/cases/fourslash/referencesForObjectLiteralProperties.ts +++ b/tests/cases/fourslash/referencesForObjectLiteralProperties.ts @@ -2,10 +2,16 @@ // References to an object literal property -////var x = { [|add|]: 0, b: "string" }; +////var x = { [|{| "isWriteAccess": true, "isDefinition": true |}add|]: 0, b: "string" }; ////x["[|add|]"]; ////x.[|add|]; ////var y = x; ////y.[|add|]; -verify.rangesReferenceEachOther(); +const ranges = test.ranges(); +const [r0, r1, r2, r3] = ranges; +verify.referenceGroups(r0, [{ definition: "(property) add: number", ranges }]); +verify.referenceGroups([r1, r2, r3], [ + { definition: "(property) add: number", ranges: [r0] }, + { definition: "(property) add: number", ranges: [r1, r2, r3] } +]); diff --git a/tests/cases/fourslash/referencesForOverrides.ts b/tests/cases/fourslash/referencesForOverrides.ts index 4896bd1cd39..5ce6bc5ed04 100644 --- a/tests/cases/fourslash/referencesForOverrides.ts +++ b/tests/cases/fourslash/referencesForOverrides.ts @@ -3,59 +3,59 @@ ////module FindRef3 { //// module SimpleClassTest { //// export class Foo { -//// public [|foo|](): void { +//// public [|{| "isWriteAccess": true, "isDefinition": true |}foo|](): void { //// } //// } //// export class Bar extends Foo { -//// public [|foo|](): void { +//// public [|{| "isWriteAccess": true, "isDefinition": true |}foo|](): void { //// } //// } //// } //// //// module SimpleInterfaceTest { //// export interface IFoo { -//// [|ifoo|](): void; +//// [|{| "isWriteAccess": true, "isDefinition": true |}ifoo|](): void; //// } //// export interface IBar extends IFoo { -//// [|ifoo|](): void; +//// [|{| "isWriteAccess": true, "isDefinition": true |}ifoo|](): void; //// } //// } //// //// module SimpleClassInterfaceTest { //// export interface IFoo { -//// [|icfoo|](): void; +//// [|{| "isWriteAccess": true, "isDefinition": true |}icfoo|](): void; //// } //// export class Bar implements IFoo { -//// public [|icfoo|](): void { +//// public [|{| "isWriteAccess": true, "isDefinition": true |}icfoo|](): void { //// } //// } //// } //// //// module Test { //// export interface IBase { -//// [|field|]: string; -//// [|method|](): void; +//// [|{| "isWriteAccess": true, "isDefinition": true |}field|]: string; +//// [|{| "isWriteAccess": true, "isDefinition": true |}method|](): void; //// } //// //// export interface IBlah extends IBase { -//// [|field|]: string; +//// [|{| "isWriteAccess": true, "isDefinition": true |}field|]: string; //// } //// //// export interface IBlah2 extends IBlah { -//// [|field|]: string; +//// [|{| "isWriteAccess": true, "isDefinition": true |}field|]: string; //// } //// //// export interface IDerived extends IBlah2 { -//// [|method|](): void; +//// [|{| "isWriteAccess": true, "isDefinition": true |}method|](): void; //// } //// //// export class Bar implements IDerived { -//// public [|field|]: string; -//// public [|method|](): void { } +//// public [|{| "isWriteAccess": true, "isDefinition": true |}field|]: string; +//// public [|{| "isWriteAccess": true, "isDefinition": true |}method|](): void { } //// } //// //// export class BarBlah extends Bar { -//// public [|field|]: string; +//// public [|{| "isWriteAccess": true, "isDefinition": true |}field|]: string; //// } //// } //// @@ -75,4 +75,67 @@ //// } ////} -verify.rangesWithSameTextReferenceEachOther(); +const ranges = test.rangesByText(); + +const fooRanges = ranges.get("foo"); +const [foo0, foo1, foo2] = fooRanges; +verify.referenceGroups(foo0, [{ definition: "(method) SimpleClassTest.Foo.foo(): void", ranges: fooRanges }]); +verify.referenceGroups([foo1, foo2], [ + { definition: "(method) SimpleClassTest.Foo.foo(): void", ranges: [foo0] }, + { definition: "(method) SimpleClassTest.Bar.foo(): void", ranges: [foo1, foo2] } +]); + +const ifooRanges = ranges.get("ifoo"); +const [ifoo0, ifoo1, ifoo2] = ifooRanges; +verify.referenceGroups(ifoo0, [{ definition: "(method) SimpleInterfaceTest.IFoo.ifoo(): void", ranges: ifooRanges }]); +verify.referenceGroups([ifoo1, ifoo2], [ + { definition: "(method) SimpleInterfaceTest.IFoo.ifoo(): void", ranges: [ifoo0] }, + { definition: "(method) SimpleInterfaceTest.IBar.ifoo(): void", ranges: [ifoo1, ifoo2] } +]); + +const icfooRanges = ranges.get("icfoo"); +const [icfoo0, icfoo1, icfoo2] = icfooRanges; +verify.referenceGroups(icfoo0, [{ definition: "(method) SimpleClassInterfaceTest.IFoo.icfoo(): void", ranges: icfooRanges }]); +verify.referenceGroups([icfoo1, icfoo2], [ + { definition: "(method) SimpleClassInterfaceTest.IFoo.icfoo(): void", ranges: [icfoo0] }, + { definition: "(method) SimpleClassInterfaceTest.Bar.icfoo(): void", ranges: [icfoo1, icfoo2] } +]); + +const fieldRanges = ranges.get("field"); +const [field0, field1, field2, field3, field4, field5] = fieldRanges; +verify.referenceGroups(field0, [{ definition: "(property) Test.IBase.field: string", ranges: fieldRanges }]); +verify.referenceGroups(field1, [ + { definition: "(property) Test.IBase.field: string", ranges: [field0] }, + { definition: "(property) Test.IBlah.field: string", ranges: fieldRanges.slice(1) } +]); +verify.referenceGroups(field2, [ + { definition: "(property) Test.IBase.field: string", ranges: [field0] }, + { definition: "(property) Test.IBlah.field: string", ranges: [field1] }, + { definition: "(property) Test.IBlah2.field: string", ranges: fieldRanges.slice(2) } +]); +verify.referenceGroups(field3, [ + { definition: "(property) Test.IBase.field: string", ranges: [field0] }, + { definition: "(property) Test.IBlah.field: string", ranges: [field1] }, + { definition: "(property) Test.IBlah2.field: string", ranges: [field2] }, + { definition: "(property) Test.Bar.field: string", ranges: fieldRanges.slice(3) } +]); +verify.referenceGroups([field4, field5], [ + { definition: "(property) Test.IBase.field: string", ranges: [field0] }, + { definition: "(property) Test.IBlah.field: string", ranges: [field1] }, + { definition: "(property) Test.IBlah2.field: string", ranges: [field2] }, + { definition: "(property) Test.Bar.field: string", ranges: [field3] }, + { definition: "(property) Test.BarBlah.field: string", ranges: fieldRanges.slice(4) } +]); + +const methodRanges = ranges.get("method"); +const [method0, method1, method2, method3] = methodRanges; +verify.referenceGroups(method0, [{ definition: "(method) Test.IBase.method(): void", ranges: methodRanges }]); +verify.referenceGroups(method1, [ + { definition: "(method) Test.IBase.method(): void", ranges: [method0] }, + { definition: "(method) Test.IDerived.method(): void", ranges: methodRanges.slice(1) } +]); +verify.referenceGroups([method2, method3], [ + { definition: "(method) Test.IBase.method(): void", ranges: [method0] }, + { definition: "(method) Test.IDerived.method(): void", ranges: [method1] }, + { definition: "(method) Test.Bar.method(): void", ranges: methodRanges.slice(2) } +]); diff --git a/tests/cases/fourslash/referencesForPropertiesOfGenericType.ts b/tests/cases/fourslash/referencesForPropertiesOfGenericType.ts index a8b08eae506..a92ac909782 100644 --- a/tests/cases/fourslash/referencesForPropertiesOfGenericType.ts +++ b/tests/cases/fourslash/referencesForPropertiesOfGenericType.ts @@ -1,7 +1,7 @@ /// ////interface IFoo { -//// [|doSomething|](v: T): T; +//// [|{| "isWriteAccess": true, "isDefinition": true |}doSomething|](v: T): T; ////} //// ////var x: IFoo; @@ -10,4 +10,14 @@ ////var y: IFoo; ////y.[|doSomething|](12); -verify.rangesReferenceEachOther(); +const ranges = test.ranges(); +const [r0, r1, r2] = ranges; +verify.referenceGroups(r0, [{ definition: "(method) IFoo.doSomething(v: T): T", ranges }]); +verify.referenceGroups(r1, [ + { definition: "(method) IFoo.doSomething(v: string): string", ranges: [r0, r2] }, + { definition: "(method) IFoo.doSomething(v: string): string", ranges: [r1] } +]); +verify.referenceGroups(r2, [ + { definition: "(method) IFoo.doSomething(v: number): number", ranges: [r0, r1] }, + { definition: "(method) IFoo.doSomething(v: number): number", ranges: [r2] } +]); diff --git a/tests/cases/fourslash/referencesForStatic.ts b/tests/cases/fourslash/referencesForStatic.ts index c6594006708..17c33daac32 100644 --- a/tests/cases/fourslash/referencesForStatic.ts +++ b/tests/cases/fourslash/referencesForStatic.ts @@ -6,7 +6,7 @@ ////var n = 43; //// ////class foo { -//// static [|n|] = ''; +//// static [|{| "isWriteAccess": true, "isDefinition": true |}n|] = ''; //// //// public bar() { //// foo.[|n|] = "'"; @@ -30,4 +30,4 @@ // @Filename: referencesOnStatic_2.ts ////var q = foo.[|n|]; -verify.rangesReferenceEachOther(); +verify.singleReferenceGroup("(property) foo.n: string"); diff --git a/tests/cases/fourslash/referencesForStaticsAndMembersWithSameNames.ts b/tests/cases/fourslash/referencesForStaticsAndMembersWithSameNames.ts index cada3e0fcf4..1e393ef6761 100644 --- a/tests/cases/fourslash/referencesForStaticsAndMembersWithSameNames.ts +++ b/tests/cases/fourslash/referencesForStaticsAndMembersWithSameNames.ts @@ -3,12 +3,12 @@ ////module FindRef4 { //// module MixedStaticsClassTest { //// export class Foo { -//// [|bar|]: Foo; -//// static [|bar|]: Foo; +//// [|{| "isWriteAccess": true, "isDefinition": true |}bar|]: Foo; +//// static [|{| "isWriteAccess": true, "isDefinition": true |}bar|]: Foo; //// -//// public [|foo|](): void { +//// public [|{| "isWriteAccess": true, "isDefinition": true |}foo|](): void { //// } -//// public static [|foo|](): void { +//// public static [|{| "isWriteAccess": true, "isDefinition": true |}foo|](): void { //// } //// } //// } @@ -28,13 +28,16 @@ const [fooBar, fooStaticBar, fooFoo, fooStaticFoo, xFoo, xBar, staticFoo, staticBar] = test.ranges(); // References to a member method with the same name as a static. -verify.referencesOf(fooFoo, [fooFoo, xFoo]); +verify.singleReferenceGroup("(method) MixedStaticsClassTest.Foo.foo(): void", [fooFoo, xFoo]); // References to a static method with the same name as a member. -verify.referencesOf(fooStaticFoo, [fooStaticFoo, staticFoo]); +verify.singleReferenceGroup("(method) MixedStaticsClassTest.Foo.foo(): void", [fooStaticFoo, staticFoo]); // References to a member property with the same name as a static. -verify.referencesOf(fooBar, [fooBar, xBar]); +//verify.singleReferenceGroup("(property) MixedStaticsClassTest.Foo.bar: Foo", [fooBar, xBar]); +verify.referenceGroups(fooBar, [{ definition: "(property) MixedStaticsClassTest.Foo.bar: Foo", ranges: [fooBar, xBar] }]); +verify.referenceGroups(xBar, [{ definition: "(property) MixedStaticsClassTest.Foo.bar: MixedStaticsClassTest.Foo", ranges: [fooBar, xBar] }]); // References to a static property with the same name as a member. -verify.referencesOf(fooStaticBar, [fooStaticBar, staticBar]); +verify.referenceGroups(fooStaticBar, [{ definition: "(property) MixedStaticsClassTest.Foo.bar: Foo", ranges: [fooStaticBar, staticBar] }]); +verify.referenceGroups(staticBar, [{ definition: "(property) MixedStaticsClassTest.Foo.bar: MixedStaticsClassTest.Foo", ranges: [fooStaticBar, staticBar] }]); diff --git a/tests/cases/fourslash/referencesForStringLiteralPropertyNames.ts b/tests/cases/fourslash/referencesForStringLiteralPropertyNames.ts index 2db0325d324..e9be352f819 100644 --- a/tests/cases/fourslash/referencesForStringLiteralPropertyNames.ts +++ b/tests/cases/fourslash/referencesForStringLiteralPropertyNames.ts @@ -1,13 +1,23 @@ /// ////class Foo { -//// public "[|ss|]": any; +//// public "[|{| "isDefinition": true |}ss|]": any; ////} //// ////var x: Foo; ////x.[|ss|]; ////x["[|ss|]"]; -////x = { "[|ss|]": 0 }; -////x = { [|ss|]: 0 }; +////x = { "[|{| "isDefinition": true |}ss|]": 0 }; +////x = { [|{| "isWriteAccess": true, "isDefinition": true |}ss|]: 0 }; -verify.rangesReferenceEachOther(); +const ranges = test.ranges(); +const [r0, r1, r2, r3, r4] = ranges; +verify.referenceGroups([r0, r1, r2], [{ definition: '(property) Foo["ss"]: any', ranges }]); +verify.referenceGroups(r3, [ + { definition: '(property) Foo["ss"]: any', ranges: [r0, r1, r2, r4] }, + { definition: '(property) "ss": number', ranges: [r3] } +]); +verify.referenceGroups(r4, [ + { definition: '(property) Foo["ss"]: any', ranges: [r0, r1, r2, r3] }, + { definition: '(property) ss: number', ranges: [r4] } +]); diff --git a/tests/cases/fourslash/referencesForStringLiteralPropertyNames2.ts b/tests/cases/fourslash/referencesForStringLiteralPropertyNames2.ts index 275a2b2756c..6fbb0b85072 100644 --- a/tests/cases/fourslash/referencesForStringLiteralPropertyNames2.ts +++ b/tests/cases/fourslash/referencesForStringLiteralPropertyNames2.ts @@ -1,10 +1,17 @@ /// ////class Foo { -//// "[|blah|]"() { return 0; } +//// "[|{| "isDefinition": true |}blah|]"() { return 0; } ////} //// ////var x: Foo; ////x.[|blah|]; -verify.rangesReferenceEachOther(); +//verify.singleReferenceGroup('(method) Foo["blah"](): number'); +const ranges = test.ranges(); +const [r0, r1] = ranges; +verify.referenceGroups(r0, [{ definition: '(method) Foo["blah"](): number', ranges }]); +verify.referenceGroups(r1, [ + { definition: '(method) Foo["blah"](): number', ranges: [r0] }, + { definition: '(method) Foo["blah"](): number', ranges: [r1] } +]); diff --git a/tests/cases/fourslash/referencesForStringLiteralPropertyNames3.ts b/tests/cases/fourslash/referencesForStringLiteralPropertyNames3.ts index 55a067ae8c3..d4e12a67afc 100644 --- a/tests/cases/fourslash/referencesForStringLiteralPropertyNames3.ts +++ b/tests/cases/fourslash/referencesForStringLiteralPropertyNames3.ts @@ -1,11 +1,17 @@ /// ////class Foo2 { -//// get "[|42|]"() { return 0; } -//// set [|42|](n) { } +//// get "[|{| "isDefinition": true |}42|]"() { return 0; } +//// set [|{| "isDefinition": true |}42|](n) { } ////} //// ////var y: Foo2; ////y[[|42|]]; -verify.rangesReferenceEachOther(); +const ranges = test.ranges(); +const [r0, r1, r2] = ranges; +verify.referenceGroups([r0, r1], [{ definition: '(property) Foo2["42"]: number', ranges }]); +verify.referenceGroups(r2, [ + { definition: '(property) Foo2["42"]: number', ranges: [r0, r1] }, + { definition: '(property) Foo2["42"]: number', ranges: [r2] }, +]); diff --git a/tests/cases/fourslash/referencesForStringLiteralPropertyNames4.ts b/tests/cases/fourslash/referencesForStringLiteralPropertyNames4.ts index 34cad8f11e8..efe8972f2c7 100644 --- a/tests/cases/fourslash/referencesForStringLiteralPropertyNames4.ts +++ b/tests/cases/fourslash/referencesForStringLiteralPropertyNames4.ts @@ -1,7 +1,13 @@ /// -////var x = { "[|someProperty|]": 0 } +////var x = { "[|{| "isDefinition": true |}someProperty|]": 0 } ////x["[|someProperty|]"] = 3; -////x./*1*/[|someProperty|] = 5; +////x.[|someProperty|] = 5; -verify.rangesReferenceEachOther(); +const ranges = test.ranges(); +const [r0, r1, r2] = ranges; +verify.referenceGroups(r0, [{ definition: '(property) "someProperty": number', ranges }]); +verify.referenceGroups([r1, r2], [ + { definition: '(property) "someProperty": number', ranges: [r0] }, + { definition: '(property) "someProperty": number', ranges: [r1, r2] }, +]); diff --git a/tests/cases/fourslash/referencesForUnionProperties.ts b/tests/cases/fourslash/referencesForUnionProperties.ts index 07eebeb5f74..97570077346 100644 --- a/tests/cases/fourslash/referencesForUnionProperties.ts +++ b/tests/cases/fourslash/referencesForUnionProperties.ts @@ -1,16 +1,16 @@ /// ////interface One { -//// common: { [|a|]: number; }; +//// common: { [|{| "isWriteAccess": true, "isDefinition": true |}a|]: number; }; ////} //// ////interface Base { -//// [|a|]: string; +//// [|{| "isWriteAccess": true, "isDefinition": true |}a|]: string; //// b: string; ////} //// ////interface HasAOrB extends Base { -//// [|a|]: string; +//// [|{| "isWriteAccess": true, "isDefinition": true |}a|]: string; //// b: string; ////} //// @@ -23,7 +23,15 @@ ////x.common.[|a|]; const [one, base, hasAOrB, x] = test.ranges(); -verify.referencesOf(one, [one, x]); -verify.referencesOf(base, [base, hasAOrB, x]); -verify.referencesOf(hasAOrB, [base, hasAOrB, x]); -verify.referencesOf(x, [one, base, hasAOrB, x]); +verify.referenceGroups(one, [{ definition: "(property) a: number", ranges: [one, x] }]); +verify.referenceGroups(base, [{ definition: "(property) Base.a: string", ranges: [base, hasAOrB, x] }]); +verify.referenceGroups(hasAOrB, [ + { definition: "(property) Base.a: string", ranges: [base] }, + { definition: "(property) HasAOrB.a: string", ranges: [hasAOrB, x] } +]); +verify.referenceGroups(x, [ + { definition: "(property) a: number", ranges: [one] }, + { definition: "(property) Base.a: string", ranges: [base] }, + { definition: "(property) HasAOrB.a: string", ranges: [hasAOrB] }, + { definition: "(property) a: string | number", ranges: [x] } +]); diff --git a/tests/cases/fourslash/referencesInComment.ts b/tests/cases/fourslash/referencesInComment.ts index eabf74d2f23..674ee41a8d2 100644 --- a/tests/cases/fourslash/referencesInComment.ts +++ b/tests/cases/fourslash/referencesInComment.ts @@ -5,4 +5,4 @@ ////class foo { } ////var bar = 0; -goTo.eachMarker(() => verify.referencesAre([])); +goTo.eachMarker(() => verify.noReferences()); diff --git a/tests/cases/fourslash/remoteGetReferences.ts b/tests/cases/fourslash/remoteGetReferences.ts index d9b6c6e852c..292864f9ed4 100644 --- a/tests/cases/fourslash/remoteGetReferences.ts +++ b/tests/cases/fourslash/remoteGetReferences.ts @@ -95,10 +95,10 @@ //////Increments ////[|remotefooCls|].[|remoteclsSVar|]++; ////remotemodTest.remotemodVar++; -////[|remoteglobalVar|] = [|remoteglobalVar|] + [|remoteglobalVar|]; +////[|{| "isWriteAccess": true |}remoteglobalVar|] = [|remoteglobalVar|] + [|remoteglobalVar|]; //// //////ETC - Other cases -////[|remoteglobalVar|] = 3; +////[|{| "isWriteAccess": true |}remoteglobalVar|] = 3; //// //////Find References misses method param ////var @@ -119,16 +119,16 @@ ////}); // @Filename: remoteGetReferences_2.ts -////var [|remoteglobalVar|]: number = 2; +////var [|{| "isWriteAccess": true, "isDefinition": true |}remoteglobalVar|]: number = 2; //// -////class [|remotefooCls|] { +////class [|{| "isWriteAccess": true, "isDefinition": true |}remotefooCls|] { //// //Declare -//// [|remoteclsVar|] = 1; -//// static [|remoteclsSVar|] = 1; +//// [|{| "isWriteAccess": true, "isDefinition": true |}remoteclsVar|] = 1; +//// static [|{| "isWriteAccess": true, "isDefinition": true |}remoteclsSVar|] = 1; //// //// constructor(public remoteclsParam: number) { //// //Increments -//// [|remoteglobalVar|]++; +//// [|{| "isWriteAccess": true |}remoteglobalVar|]++; //// this.[|remoteclsVar|]++; //// [|remotefooCls|].[|remoteclsSVar|]++; //// this.remoteclsParam++; @@ -142,7 +142,7 @@ //// //// //Increments //// [|remotefooCls|].[|remoteclsSVar|]++; -//// [|remoteglobalVar|]++; +//// [|{| "isWriteAccess": true |}remoteglobalVar|]++; //// remotemodTest.remotemodVar++; //// remotefnVar++; //// @@ -155,7 +155,7 @@ //// export var remotemodVar: number; //// //// //Increments -//// [|remoteglobalVar|]++; +//// [|{| "isWriteAccess": true |}remoteglobalVar|]++; //// [|remotefooCls|].[|remoteclsSVar|]++; //// remotemodVar++; //// @@ -167,7 +167,7 @@ //// static remoteboo = remotefoo; //// //// //Increments -//// [|remoteglobalVar|]++; +//// [|{| "isWriteAccess": true |}remoteglobalVar|]++; //// [|remotefooCls|].[|remoteclsSVar|]++; //// remotemodVar++; //// } @@ -177,4 +177,24 @@ //// } ////} -verify.rangesWithSameTextReferenceEachOther(); +test.rangesByText().forEach((ranges, text) => { + const definition = (() => { + switch (text) { + case "remotefooCls": return "class remotefooCls"; + case "remoteglobalVar": return "var remoteglobalVar: number"; + case "remoteclsSVar": return "(property) remotefooCls.remoteclsSVar: number"; + case "remoteclsVar": return "(property) remotefooCls.remoteclsVar: number"; + default: throw new Error(text); + } + })(); + + if (text === "remotefooCls") { + verify.referenceGroups([ranges[0], ...ranges.slice(2)], [{ definition, ranges }]); + verify.referenceGroups(ranges[1], [ + { definition: "constructor remotefooCls(remoteclsParam: number): remotefooCls", ranges} + ]); + } + else { + verify.singleReferenceGroup(definition, ranges); + } +}); diff --git a/tests/cases/fourslash/renameDefaultImport.ts b/tests/cases/fourslash/renameDefaultImport.ts index ff297ffa147..bcac46d7a63 100644 --- a/tests/cases/fourslash/renameDefaultImport.ts +++ b/tests/cases/fourslash/renameDefaultImport.ts @@ -1,21 +1,23 @@ /// // @Filename: B.ts -////export default class /*1*/[|B|] { +////export default class /*1*/[|{| "isWriteAccess": true, "isDefinition": true |}B|] { //// test() { //// } ////} // @Filename: A.ts -////import [|B|] from "./B"; +////import [|{| "isWriteAccess": true, "isDefinition": true |}B|] from "./B"; ////let b = new [|B|](); ////b.test(); goTo.marker("1"); verify.occurrencesAtPositionCount(1); -const [C, B0, B1] = test.ranges(); -verify.rangesReferenceEachOther(); +const ranges = test.ranges(); +const [C, B0, B1] = ranges; +verify.referenceGroups([C, B0], [{ definition: "class B", ranges }]); +verify.referenceGroups(B1, [{ definition: "constructor B(): B", ranges }]); goTo.rangeStart(C); verify.renameLocations(false, false, [C, B0, B1]); diff --git a/tests/cases/fourslash/renameDefaultImportDifferentName.ts b/tests/cases/fourslash/renameDefaultImportDifferentName.ts index be968c9b883..590c81c650c 100644 --- a/tests/cases/fourslash/renameDefaultImportDifferentName.ts +++ b/tests/cases/fourslash/renameDefaultImportDifferentName.ts @@ -1,21 +1,23 @@ /// // @Filename: B.ts -////export default class /*1*/[|C|] { +////export default class /*1*/[|{| "isWriteAccess": true, "isDefinition": true |}C|] { //// test() { //// } ////} // @Filename: A.ts -////import [|B|] from "./B"; +////import [|{| "isWriteAccess": true, "isDefinition": true |}B|] from "./B"; ////let b = new [|B|](); ////b.test(); goTo.marker("1"); verify.occurrencesAtPositionCount(1); -const [C, B0, B1] = test.ranges(); -verify.rangesReferenceEachOther(); +const ranges = test.ranges(); +const [C, B0, B1] = ranges; +verify.referenceGroups([C, B0], [{ definition: "class C", ranges }]); +verify.referenceGroups(B1, [{ definition: "constructor C(): B", ranges }]); goTo.rangeStart(C); verify.renameLocations(false, false, [C, B0, B1]); diff --git a/tests/cases/fourslash/renameImportAndExportInDiffFiles.ts b/tests/cases/fourslash/renameImportAndExportInDiffFiles.ts index e982d6a4c7b..656a48f24dd 100644 --- a/tests/cases/fourslash/renameImportAndExportInDiffFiles.ts +++ b/tests/cases/fourslash/renameImportAndExportInDiffFiles.ts @@ -1,10 +1,10 @@ /// // @Filename: a.ts -////export var [|a|]; +////export var [|{| "isWriteAccess": true, "isDefinition": true |}a|]; // @Filename: b.ts -////import { [|a|] } from './a'; -////export { [|a|] }; +////import { [|{| "isWriteAccess": true, "isDefinition": true |}a|] } from './a'; +////export { [|{| "isWriteAccess": true, "isDefinition": true |}a|] }; -verify.rangesReferenceEachOther(); +verify.singleReferenceGroup("var a: any"); diff --git a/tests/cases/fourslash/shims-pp/getReferencesAtPosition.ts b/tests/cases/fourslash/shims-pp/getReferencesAtPosition.ts index cb829807602..fa9a510d5ac 100644 --- a/tests/cases/fourslash/shims-pp/getReferencesAtPosition.ts +++ b/tests/cases/fourslash/shims-pp/getReferencesAtPosition.ts @@ -1,4 +1,4 @@ -/// +/// //@Filename: findAllRefsOnDefinition-import.ts ////export class Test{ @@ -7,7 +7,7 @@ //// //// } //// -//// public [|start|](){ +//// public [|{| "isWriteAccess": true, "isDefinition": true |}start|](){ //// return this; //// } //// @@ -23,4 +23,10 @@ ////second.[|start|](); ////second.stop(); -verify.rangesReferenceEachOther(); +const ranges = test.ranges(); +const [r0, r1] = ranges; +verify.referenceGroups(r0, [{ definition: "(method) Test.start(): this", ranges }]); +verify.referenceGroups(r1, [ + { definition: "(method) Second.Test.start(): Second.Test", ranges: [r0] }, + { definition: "(method) Second.Test.start(): Second.Test", ranges: [r1] } +]); diff --git a/tests/cases/fourslash/shims/getReferencesAtPosition.ts b/tests/cases/fourslash/shims/getReferencesAtPosition.ts index cb829807602..fa9a510d5ac 100644 --- a/tests/cases/fourslash/shims/getReferencesAtPosition.ts +++ b/tests/cases/fourslash/shims/getReferencesAtPosition.ts @@ -1,4 +1,4 @@ -/// +/// //@Filename: findAllRefsOnDefinition-import.ts ////export class Test{ @@ -7,7 +7,7 @@ //// //// } //// -//// public [|start|](){ +//// public [|{| "isWriteAccess": true, "isDefinition": true |}start|](){ //// return this; //// } //// @@ -23,4 +23,10 @@ ////second.[|start|](); ////second.stop(); -verify.rangesReferenceEachOther(); +const ranges = test.ranges(); +const [r0, r1] = ranges; +verify.referenceGroups(r0, [{ definition: "(method) Test.start(): this", ranges }]); +verify.referenceGroups(r1, [ + { definition: "(method) Second.Test.start(): Second.Test", ranges: [r0] }, + { definition: "(method) Second.Test.start(): Second.Test", ranges: [r1] } +]); diff --git a/tests/cases/fourslash/untypedModuleImport.ts b/tests/cases/fourslash/untypedModuleImport.ts index da6473cf992..1854010d5b6 100644 --- a/tests/cases/fourslash/untypedModuleImport.ts +++ b/tests/cases/fourslash/untypedModuleImport.ts @@ -4,7 +4,7 @@ ////{} // @Filename: a.ts -////import /*foo*/[|foo|] from /*fooModule*/"foo"; +////import /*foo*/[|{| "isWriteAccess": true, "isDefinition": true |}foo|] from /*fooModule*/"foo"; ////[|foo|](); goTo.file("a.ts"); @@ -13,9 +13,9 @@ verify.numberOfErrorsInCurrentFile(0); goTo.marker("fooModule"); verify.goToDefinitionIs([]); verify.quickInfoIs(""); -verify.referencesAre([]) +verify.noReferences(); goTo.marker("foo"); verify.goToDefinitionIs([]); verify.quickInfoIs("import foo"); -verify.rangesReferenceEachOther(); +verify.singleReferenceGroup("import foo"); From d77945fe1f426ef5b7e1d110125a628013a83d16 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Tue, 31 Jan 2017 10:28:02 -0800 Subject: [PATCH 12/58] typeof now has string literal union type Previously, it was just a string --- src/compiler/checker.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 26c27cb3be2..47811d6ccaf 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -14609,7 +14609,9 @@ namespace ts { function checkTypeOfExpression(node: TypeOfExpression): Type { checkExpression(node.expression); - return stringType; + const types: Type[] = []; + typeofEQFacts.forEach((_, s) => types.push(getLiteralTypeForText(TypeFlags.StringLiteral, s))); + return getUnionType(types); } function checkVoidExpression(node: VoidExpression): Type { From 69e9bfef356ed904d35ec601ff0d00f4c842a7d3 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Tue, 31 Jan 2017 10:28:32 -0800 Subject: [PATCH 13/58] Add typeof test case and update baselines Test that `typeof x === 'random' as string`: 1. Does not issue an error. 2. Does not narrow. --- .../reference/TypeGuardWithEnumUnion.types | 8 +- .../reference/anonymousClassExpression1.types | 2 +- ...WithoutReturnTypeAnnotationInference.types | 10 +- .../reference/castExpressionParentheses.types | 2 +- tests/baselines/reference/castOfAwait.types | 4 +- .../classDoesNotDependOnBaseTypes.types | 2 +- ...tionalOperatorConditionIsBooleanType.types | 6 +- ...itionalOperatorConditoinIsStringType.types | 6 +- .../constLocalsInFunctionExpressions.types | 10 +- .../reference/controlFlowCommaOperator.types | 4 +- .../controlFlowDoWhileStatement.types | 2 +- .../reference/controlFlowForStatement.types | 8 +- .../baselines/reference/controlFlowIIFE.types | 6 +- .../reference/controlFlowIfStatement.types | 4 +- .../reference/controlFlowWhileStatement.types | 2 +- .../controlFlowWithIncompleteTypes.types | 4 +- ...eclarationEmitIdentifierPredicates01.types | 2 +- .../discriminantsAndPrimitives.types | 8 +- ...onentiationOperatorInTempalteString4.types | 8 +- ...ntiationOperatorInTempalteString4ES6.types | 8 +- ...onentiationOperatorInTemplateString1.types | 12 +- ...ntiationOperatorInTemplateString1ES6.types | 12 +- ...onentiationOperatorInTemplateString2.types | 12 +- ...ntiationOperatorInTemplateString2ES6.types | 12 +- ...onentiationOperatorInTemplateString3.types | 12 +- ...ntiationOperatorInTemplateString3ES6.types | 12 +- .../interfaceDoesNotDependOnBaseTypes.types | 2 +- tests/baselines/reference/mappedTypes4.types | 2 +- .../narrowingConstrainedTypeParameter.types | 2 +- .../reference/nestedLoopTypeGuards.types | 8 +- tests/baselines/reference/neverType.types | 4 +- .../overloadResolutionOverNonCTLambdas.types | 2 +- .../reference/overloadReturnTypes.types | 2 +- ...fixUnaryOperatorsOnExportedVariables.types | 2 +- tests/baselines/reference/symbolType17.types | 2 +- tests/baselines/reference/symbolType18.types | 2 +- tests/baselines/reference/symbolType19.types | 2 +- .../reference/templateStringInTypeOf.types | 4 +- .../reference/templateStringInTypeOfES6.types | 4 +- ...lateStringWithEmbeddedTypeOfOperator.types | 2 +- ...eStringWithEmbeddedTypeOfOperatorES6.types | 2 +- .../baselines/reference/throwStatements.types | 2 +- .../baselines/reference/typeGuardEnums.types | 4 +- .../typeGuardIntersectionTypes.types | 2 +- .../reference/typeGuardNesting.types | 24 +-- .../typeGuardOfFormExpr1AndExpr2.types | 18 +- .../typeGuardOfFormExpr1OrExpr2.types | 18 +- .../reference/typeGuardOfFormNotExpr.types | 20 +- .../typeGuardOfFormTypeOfBoolean.types | 20 +- ...FormTypeOfEqualEqualHasNoEffect.errors.txt | 5 +- ...eGuardOfFormTypeOfIsOrderIndependent.types | 8 +- ...OfFormTypeOfNotEqualHasNoEffect.errors.txt | 5 +- .../typeGuardOfFormTypeOfNumber.types | 20 +- .../typeGuardOfFormTypeOfOther.errors.txt | 118 +++++++++++ .../reference/typeGuardOfFormTypeOfOther.js | 12 ++ .../typeGuardOfFormTypeOfOther.symbols | 153 --------------- .../typeGuardOfFormTypeOfOther.types | 183 ------------------ ...ypeGuardOfFormTypeOfPrimitiveSubtype.types | 12 +- .../typeGuardOfFormTypeOfString.types | 20 +- .../reference/typeGuardRedundancy.types | 16 +- .../typeGuardTautologicalConsistiency.types | 8 +- .../reference/typeGuardTypeOfUndefined.types | 64 +++--- .../reference/typeGuardsAsAssertions.types | 12 +- .../typeGuardsInClassAccessors.types | 40 ++-- .../reference/typeGuardsInClassMethods.types | 30 +-- .../typeGuardsInConditionalExpression.types | 34 ++-- .../reference/typeGuardsInDoStatement.types | 6 +- .../typeGuardsInExternalModule.types | 4 +- .../reference/typeGuardsInForStatement.types | 6 +- .../reference/typeGuardsInFunction.types | 38 ++-- .../typeGuardsInFunctionAndModuleBlock.types | 26 +-- .../reference/typeGuardsInGlobal.types | 2 +- .../reference/typeGuardsInModule.types | 22 +-- .../reference/typeGuardsInProperties.types | 12 +- ...GuardsInRightOperandOfAndAndOperator.types | 22 +-- ...peGuardsInRightOperandOfOrOrOperator.types | 22 +-- .../typeGuardsInWhileStatement.types | 6 +- .../typeGuardsNestedAssignments.types | 2 +- .../reference/typeGuardsObjectMethods.types | 20 +- .../reference/typeGuardsOnClassProperty.types | 8 +- .../reference/typeOfOperator1.errors.txt | 6 +- .../typeGuards/typeGuardOfFormTypeOfOther.ts | 6 + 82 files changed, 542 insertions(+), 734 deletions(-) create mode 100644 tests/baselines/reference/typeGuardOfFormTypeOfOther.errors.txt delete mode 100644 tests/baselines/reference/typeGuardOfFormTypeOfOther.symbols delete mode 100644 tests/baselines/reference/typeGuardOfFormTypeOfOther.types diff --git a/tests/baselines/reference/TypeGuardWithEnumUnion.types b/tests/baselines/reference/TypeGuardWithEnumUnion.types index d33411c4c7c..8ee4aaca363 100644 --- a/tests/baselines/reference/TypeGuardWithEnumUnion.types +++ b/tests/baselines/reference/TypeGuardWithEnumUnion.types @@ -12,7 +12,7 @@ function f1(x: Color | string) { if (typeof x === "number") { >typeof x === "number" : boolean ->typeof x : string +>typeof x : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >x : string | Color >"number" : "number" @@ -41,7 +41,7 @@ function f2(x: Color | string | string[]) { if (typeof x === "object") { >typeof x === "object" : boolean ->typeof x : string +>typeof x : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >x : string | Color | string[] >"object" : "object" @@ -54,7 +54,7 @@ function f2(x: Color | string | string[]) { } if (typeof x === "number") { >typeof x === "number" : boolean ->typeof x : string +>typeof x : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >x : string | Color | string[] >"number" : "number" @@ -76,7 +76,7 @@ function f2(x: Color | string | string[]) { } if (typeof x === "string") { >typeof x === "string" : boolean ->typeof x : string +>typeof x : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >x : string | Color | string[] >"string" : "string" diff --git a/tests/baselines/reference/anonymousClassExpression1.types b/tests/baselines/reference/anonymousClassExpression1.types index 0fbffffdf4b..3bc01960492 100644 --- a/tests/baselines/reference/anonymousClassExpression1.types +++ b/tests/baselines/reference/anonymousClassExpression1.types @@ -4,7 +4,7 @@ function f() { return typeof class {} === "function"; >typeof class {} === "function" : boolean ->typeof class {} : string +>typeof class {} : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >class {} : typeof (Anonymous class) >"function" : "function" } diff --git a/tests/baselines/reference/callSignatureWithoutReturnTypeAnnotationInference.types b/tests/baselines/reference/callSignatureWithoutReturnTypeAnnotationInference.types index 0b515750aec..658eff38bbb 100644 --- a/tests/baselines/reference/callSignatureWithoutReturnTypeAnnotationInference.types +++ b/tests/baselines/reference/callSignatureWithoutReturnTypeAnnotationInference.types @@ -103,17 +103,17 @@ var r6 = foo6(1); >1 : 1 function foo7(x) { ->foo7 : (x: any) => string +>foo7 : (x: any) => "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >x : any return typeof x; ->typeof x : string +>typeof x : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >x : any } var r7 = foo7(1); ->r7 : string ->foo7(1) : string ->foo7 : (x: any) => string +>r7 : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" +>foo7(1) : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" +>foo7 : (x: any) => "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >1 : 1 // object types diff --git a/tests/baselines/reference/castExpressionParentheses.types b/tests/baselines/reference/castExpressionParentheses.types index dafe3377aea..aa633825eec 100644 --- a/tests/baselines/reference/castExpressionParentheses.types +++ b/tests/baselines/reference/castExpressionParentheses.types @@ -182,7 +182,7 @@ declare var A; >(typeof A).x : any >(typeof A) : any >typeof A : any ->typeof A : string +>typeof A : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >A : any >x : any diff --git a/tests/baselines/reference/castOfAwait.types b/tests/baselines/reference/castOfAwait.types index 30220ca2ab6..805affe49db 100644 --- a/tests/baselines/reference/castOfAwait.types +++ b/tests/baselines/reference/castOfAwait.types @@ -8,7 +8,7 @@ async function f() { >0 : 0 typeof await 0; ->typeof await 0 : string +>typeof await 0 : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >await 0 : 0 >0 : 0 @@ -21,7 +21,7 @@ async function f() { >await void typeof void await 0 : any >void typeof void await 0 : undefined > typeof void await 0 : string ->typeof void await 0 : string +>typeof void await 0 : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" > void await 0 : number >void await 0 : undefined >await 0 : 0 diff --git a/tests/baselines/reference/classDoesNotDependOnBaseTypes.types b/tests/baselines/reference/classDoesNotDependOnBaseTypes.types index 5ac20c6e0fa..54b67dfd6a7 100644 --- a/tests/baselines/reference/classDoesNotDependOnBaseTypes.types +++ b/tests/baselines/reference/classDoesNotDependOnBaseTypes.types @@ -5,7 +5,7 @@ var x: StringTree; if (typeof x !== "string") { >typeof x !== "string" : boolean ->typeof x : string +>typeof x : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >x : StringTree >"string" : "string" diff --git a/tests/baselines/reference/conditionalOperatorConditionIsBooleanType.types b/tests/baselines/reference/conditionalOperatorConditionIsBooleanType.types index f19769b1c58..610b80ef612 100644 --- a/tests/baselines/reference/conditionalOperatorConditionIsBooleanType.types +++ b/tests/baselines/reference/conditionalOperatorConditionIsBooleanType.types @@ -120,7 +120,7 @@ true ? exprString1 : exprBoolean1; // union typeof "123" == "string" ? exprBoolean1 : exprBoolean2; >typeof "123" == "string" ? exprBoolean1 : exprBoolean2 : boolean >typeof "123" == "string" : boolean ->typeof "123" : string +>typeof "123" : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >"123" : "123" >"string" : "string" >exprBoolean1 : boolean @@ -262,7 +262,7 @@ var resultIsBoolean3 = typeof "123" == "string" ? exprBoolean1 : exprBoolean2; >resultIsBoolean3 : boolean >typeof "123" == "string" ? exprBoolean1 : exprBoolean2 : boolean >typeof "123" == "string" : boolean ->typeof "123" : string +>typeof "123" : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >"123" : "123" >"string" : "string" >exprBoolean1 : boolean @@ -299,7 +299,7 @@ var resultIsStringOrBoolean4 = typeof "123" === "string" ? exprString1 : exprBoo >resultIsStringOrBoolean4 : string | boolean >typeof "123" === "string" ? exprString1 : exprBoolean1 : string | boolean >typeof "123" === "string" : boolean ->typeof "123" : string +>typeof "123" : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >"123" : "123" >"string" : "string" >exprString1 : string diff --git a/tests/baselines/reference/conditionalOperatorConditoinIsStringType.types b/tests/baselines/reference/conditionalOperatorConditoinIsStringType.types index a6906d7024a..33e34bea635 100644 --- a/tests/baselines/reference/conditionalOperatorConditoinIsStringType.types +++ b/tests/baselines/reference/conditionalOperatorConditoinIsStringType.types @@ -123,7 +123,7 @@ var array = ["1", "2", "3"]; typeof condString ? exprAny1 : exprAny2; >typeof condString ? exprAny1 : exprAny2 : any ->typeof condString : string +>typeof condString : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >condString : string >exprAny1 : any >exprAny2 : any @@ -254,7 +254,7 @@ var resultIsStringOrBoolean2 = "hello" ? exprString1 : exprBoolean1; // union var resultIsAny3 = typeof condString ? exprAny1 : exprAny2; >resultIsAny3 : any >typeof condString ? exprAny1 : exprAny2 : any ->typeof condString : string +>typeof condString : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >condString : string >exprAny1 : any >exprAny2 : any @@ -297,7 +297,7 @@ var resultIsObject3 = array[1] ? exprIsObject1 : exprIsObject2; var resultIsStringOrBoolean3 = typeof condString ? exprString1 : exprBoolean1; // union >resultIsStringOrBoolean3 : string | boolean >typeof condString ? exprString1 : exprBoolean1 : string | boolean ->typeof condString : string +>typeof condString : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >condString : string >exprString1 : string >exprBoolean1 : boolean diff --git a/tests/baselines/reference/constLocalsInFunctionExpressions.types b/tests/baselines/reference/constLocalsInFunctionExpressions.types index db1da04e0ca..07d3392045c 100644 --- a/tests/baselines/reference/constLocalsInFunctionExpressions.types +++ b/tests/baselines/reference/constLocalsInFunctionExpressions.types @@ -12,7 +12,7 @@ function f1() { if (typeof x === "string") { >typeof x === "string" : boolean ->typeof x : string +>typeof x : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >x : string | number >"string" : "string" @@ -35,7 +35,7 @@ function f2() { if (typeof x !== "string") { >typeof x !== "string" : boolean ->typeof x : string +>typeof x : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >x : string | number >"string" : "string" @@ -59,7 +59,7 @@ function f3() { if (typeof x === "string") { >typeof x === "string" : boolean ->typeof x : string +>typeof x : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >x : string | number >"string" : "string" @@ -82,7 +82,7 @@ function f4() { if (typeof x !== "string") { >typeof x !== "string" : boolean ->typeof x : string +>typeof x : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >x : string | number >"string" : "string" @@ -106,7 +106,7 @@ function f5() { if (typeof x === "string") { >typeof x === "string" : boolean ->typeof x : string +>typeof x : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >x : string | number >"string" : "string" diff --git a/tests/baselines/reference/controlFlowCommaOperator.types b/tests/baselines/reference/controlFlowCommaOperator.types index 52fd3d7b87d..d4e073295d7 100644 --- a/tests/baselines/reference/controlFlowCommaOperator.types +++ b/tests/baselines/reference/controlFlowCommaOperator.types @@ -17,7 +17,7 @@ function f(x: string | number | boolean) { >y : string | number | boolean >"" : "" >typeof x === "string" : boolean ->typeof x : string +>typeof x : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >x : string | number | boolean >"string" : "string" @@ -36,7 +36,7 @@ function f(x: string | number | boolean) { >z : string | number | boolean >1 : 1 >typeof x === "number" : boolean ->typeof x : string +>typeof x : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >x : number | boolean >"number" : "number" diff --git a/tests/baselines/reference/controlFlowDoWhileStatement.types b/tests/baselines/reference/controlFlowDoWhileStatement.types index 24f3e92b144..baa585bc14d 100644 --- a/tests/baselines/reference/controlFlowDoWhileStatement.types +++ b/tests/baselines/reference/controlFlowDoWhileStatement.types @@ -66,7 +66,7 @@ function c() { if (typeof x === "string") continue; >typeof x === "string" : boolean ->typeof x : string +>typeof x : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >x : string | number >"string" : "string" diff --git a/tests/baselines/reference/controlFlowForStatement.types b/tests/baselines/reference/controlFlowForStatement.types index d227e87ea1d..f82a018573b 100644 --- a/tests/baselines/reference/controlFlowForStatement.types +++ b/tests/baselines/reference/controlFlowForStatement.types @@ -82,7 +82,7 @@ function d() { >x : string | number | boolean >"" : "" >typeof x === "string" : boolean ->typeof x : string +>typeof x : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >x : string | number >"string" : "string" >x = 5 : 5 @@ -107,7 +107,7 @@ function e() { >"" : "" >0 : 0 >typeof x !== "string" : boolean ->typeof x : string +>typeof x : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >x : number | true >"string" : "string" >x = "" || true : true @@ -128,7 +128,7 @@ function f() { for (; typeof x !== "string";) { >typeof x !== "string" : boolean ->typeof x : string +>typeof x : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >x : string | number | boolean >"string" : "string" @@ -137,7 +137,7 @@ function f() { if (typeof x === "number") break; >typeof x === "number" : boolean ->typeof x : string +>typeof x : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >x : number | boolean >"number" : "number" diff --git a/tests/baselines/reference/controlFlowIIFE.types b/tests/baselines/reference/controlFlowIIFE.types index 7cf4337b53b..1c2e8290394 100644 --- a/tests/baselines/reference/controlFlowIIFE.types +++ b/tests/baselines/reference/controlFlowIIFE.types @@ -13,7 +13,7 @@ function f1() { if (typeof x === "string") { >typeof x === "string" : boolean ->typeof x : string +>typeof x : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >x : string | number >"string" : "string" @@ -41,7 +41,7 @@ function f2() { if (typeof x === "string") { >typeof x === "string" : boolean ->typeof x : string +>typeof x : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >x : string | number >"string" : "string" @@ -73,7 +73,7 @@ function f3() { if (typeof x === "string") { >typeof x === "string" : boolean ->typeof x : string +>typeof x : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >x : string | number >"string" : "string" diff --git a/tests/baselines/reference/controlFlowIfStatement.types b/tests/baselines/reference/controlFlowIfStatement.types index fd8f25b9ee3..e0ce68db7b1 100644 --- a/tests/baselines/reference/controlFlowIfStatement.types +++ b/tests/baselines/reference/controlFlowIfStatement.types @@ -100,7 +100,7 @@ function c(data: string | T): T { if (typeof data === 'string') { >typeof data === 'string' : boolean ->typeof data : string +>typeof data : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >data : string | T >'string' : "string" @@ -124,7 +124,7 @@ function d(data: string | T): never { if (typeof data === 'string') { >typeof data === 'string' : boolean ->typeof data : string +>typeof data : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >data : string | T >'string' : "string" diff --git a/tests/baselines/reference/controlFlowWhileStatement.types b/tests/baselines/reference/controlFlowWhileStatement.types index 19f7fc49d02..4576e1a4f62 100644 --- a/tests/baselines/reference/controlFlowWhileStatement.types +++ b/tests/baselines/reference/controlFlowWhileStatement.types @@ -69,7 +69,7 @@ function c() { if (typeof x === "string") continue; >typeof x === "string" : boolean ->typeof x : string +>typeof x : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >x : string | number >"string" : "string" diff --git a/tests/baselines/reference/controlFlowWithIncompleteTypes.types b/tests/baselines/reference/controlFlowWithIncompleteTypes.types index 784f22a3966..f5e8f2bcf24 100644 --- a/tests/baselines/reference/controlFlowWithIncompleteTypes.types +++ b/tests/baselines/reference/controlFlowWithIncompleteTypes.types @@ -16,7 +16,7 @@ function foo1() { if (typeof x === "string") { >typeof x === "string" : boolean ->typeof x : string +>typeof x : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >x : string | number >"string" : "string" @@ -49,7 +49,7 @@ function foo2() { if (typeof x === "number") { >typeof x === "number" : boolean ->typeof x : string +>typeof x : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >x : string | number >"number" : "number" diff --git a/tests/baselines/reference/declarationEmitIdentifierPredicates01.types b/tests/baselines/reference/declarationEmitIdentifierPredicates01.types index 1129012a80a..1aeb3ea824d 100644 --- a/tests/baselines/reference/declarationEmitIdentifierPredicates01.types +++ b/tests/baselines/reference/declarationEmitIdentifierPredicates01.types @@ -7,7 +7,7 @@ export function f(x: any): x is number { return typeof x === "number"; >typeof x === "number" : boolean ->typeof x : string +>typeof x : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >x : any >"number" : "number" } diff --git a/tests/baselines/reference/discriminantsAndPrimitives.types b/tests/baselines/reference/discriminantsAndPrimitives.types index d3e1b70e599..0870d17948f 100644 --- a/tests/baselines/reference/discriminantsAndPrimitives.types +++ b/tests/baselines/reference/discriminantsAndPrimitives.types @@ -30,7 +30,7 @@ function f1(x: Foo | Bar | string) { if (typeof x !== 'string') { >typeof x !== 'string' : boolean ->typeof x : string +>typeof x : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >x : string | Foo | Bar >'string' : "string" @@ -58,7 +58,7 @@ function f2(x: Foo | Bar | string | undefined) { if (typeof x === "object") { >typeof x === "object" : boolean ->typeof x : string +>typeof x : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >x : string | Foo | Bar | undefined >"object" : "object" @@ -89,7 +89,7 @@ function f3(x: Foo | Bar | string | null) { >x && typeof x !== "string" : boolean | "" | null >x : string | Foo | Bar | null >typeof x !== "string" : boolean ->typeof x : string +>typeof x : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >x : string | Foo | Bar >"string" : "string" @@ -120,7 +120,7 @@ function f4(x: Foo | Bar | string | number | null) { >x && typeof x === "object" : boolean | "" | 0 | null >x : string | number | Foo | Bar | null >typeof x === "object" : boolean ->typeof x : string +>typeof x : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >x : string | number | Foo | Bar >"object" : "object" diff --git a/tests/baselines/reference/emitExponentiationOperatorInTempalteString4.types b/tests/baselines/reference/emitExponentiationOperatorInTempalteString4.types index 7991ef224f0..d11846227f2 100644 --- a/tests/baselines/reference/emitExponentiationOperatorInTempalteString4.types +++ b/tests/baselines/reference/emitExponentiationOperatorInTempalteString4.types @@ -64,7 +64,7 @@ var s; `${typeof (t1 ** t2 ** t1) } world`; >`${typeof (t1 ** t2 ** t1) } world` : string ->typeof (t1 ** t2 ** t1) : string +>typeof (t1 ** t2 ** t1) : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >(t1 ** t2 ** t1) : number >t1 ** t2 ** t1 : number >t1 : number @@ -162,14 +162,14 @@ var s; `${typeof (t1 ** t2 ** t1)} hello world ${typeof (t1 ** t2 ** t1)}`; >`${typeof (t1 ** t2 ** t1)} hello world ${typeof (t1 ** t2 ** t1)}` : string ->typeof (t1 ** t2 ** t1) : string +>typeof (t1 ** t2 ** t1) : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >(t1 ** t2 ** t1) : number >t1 ** t2 ** t1 : number >t1 : number >t2 ** t1 : number >t2 : number >t1 : number ->typeof (t1 ** t2 ** t1) : string +>typeof (t1 ** t2 ** t1) : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >(t1 ** t2 ** t1) : number >t1 ** t2 ** t1 : number >t1 : number @@ -223,7 +223,7 @@ var s; `hello ${typeof (t1 ** t2 ** t1)}`; >`hello ${typeof (t1 ** t2 ** t1)}` : string ->typeof (t1 ** t2 ** t1) : string +>typeof (t1 ** t2 ** t1) : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >(t1 ** t2 ** t1) : number >t1 ** t2 ** t1 : number >t1 : number diff --git a/tests/baselines/reference/emitExponentiationOperatorInTempalteString4ES6.types b/tests/baselines/reference/emitExponentiationOperatorInTempalteString4ES6.types index 981829dd42b..610c3a64a6e 100644 --- a/tests/baselines/reference/emitExponentiationOperatorInTempalteString4ES6.types +++ b/tests/baselines/reference/emitExponentiationOperatorInTempalteString4ES6.types @@ -64,7 +64,7 @@ var s; `${typeof (t1 ** t2 ** t1) } world`; >`${typeof (t1 ** t2 ** t1) } world` : string ->typeof (t1 ** t2 ** t1) : string +>typeof (t1 ** t2 ** t1) : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >(t1 ** t2 ** t1) : number >t1 ** t2 ** t1 : number >t1 : number @@ -162,14 +162,14 @@ var s; `${typeof (t1 ** t2 ** t1)} hello world ${typeof (t1 ** t2 ** t1)}`; >`${typeof (t1 ** t2 ** t1)} hello world ${typeof (t1 ** t2 ** t1)}` : string ->typeof (t1 ** t2 ** t1) : string +>typeof (t1 ** t2 ** t1) : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >(t1 ** t2 ** t1) : number >t1 ** t2 ** t1 : number >t1 : number >t2 ** t1 : number >t2 : number >t1 : number ->typeof (t1 ** t2 ** t1) : string +>typeof (t1 ** t2 ** t1) : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >(t1 ** t2 ** t1) : number >t1 ** t2 ** t1 : number >t1 : number @@ -223,7 +223,7 @@ var s; `hello ${typeof (t1 ** t2 ** t1)}`; >`hello ${typeof (t1 ** t2 ** t1)}` : string ->typeof (t1 ** t2 ** t1) : string +>typeof (t1 ** t2 ** t1) : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >(t1 ** t2 ** t1) : number >t1 ** t2 ** t1 : number >t1 : number diff --git a/tests/baselines/reference/emitExponentiationOperatorInTemplateString1.types b/tests/baselines/reference/emitExponentiationOperatorInTemplateString1.types index bbfb5b88e04..4f78cd61fcc 100644 --- a/tests/baselines/reference/emitExponentiationOperatorInTemplateString1.types +++ b/tests/baselines/reference/emitExponentiationOperatorInTemplateString1.types @@ -54,7 +54,7 @@ var s; `${typeof (t1 ** t2 ** t1) }`; >`${typeof (t1 ** t2 ** t1) }` : string ->typeof (t1 ** t2 ** t1) : string +>typeof (t1 ** t2 ** t1) : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >(t1 ** t2 ** t1) : number >t1 ** t2 ** t1 : number >t1 : number @@ -66,7 +66,7 @@ var s; >`${1 + typeof (t1 ** t2 ** t1) }` : string >1 + typeof (t1 ** t2 ** t1) : string >1 : 1 ->typeof (t1 ** t2 ** t1) : string +>typeof (t1 ** t2 ** t1) : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >(t1 ** t2 ** t1) : number >t1 ** t2 ** t1 : number >t1 : number @@ -141,14 +141,14 @@ var s; `${typeof (t1 ** t2 ** t1)}${typeof (t1 ** t2 ** t1)}`; >`${typeof (t1 ** t2 ** t1)}${typeof (t1 ** t2 ** t1)}` : string ->typeof (t1 ** t2 ** t1) : string +>typeof (t1 ** t2 ** t1) : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >(t1 ** t2 ** t1) : number >t1 ** t2 ** t1 : number >t1 : number >t2 ** t1 : number >t2 : number >t1 : number ->typeof (t1 ** t2 ** t1) : string +>typeof (t1 ** t2 ** t1) : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >(t1 ** t2 ** t1) : number >t1 ** t2 ** t1 : number >t1 : number @@ -223,14 +223,14 @@ var s; `${typeof (t1 ** t2 ** t1) } hello world ${typeof (t1 ** t2 ** t1) }`; >`${typeof (t1 ** t2 ** t1) } hello world ${typeof (t1 ** t2 ** t1) }` : string ->typeof (t1 ** t2 ** t1) : string +>typeof (t1 ** t2 ** t1) : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >(t1 ** t2 ** t1) : number >t1 ** t2 ** t1 : number >t1 : number >t2 ** t1 : number >t2 : number >t1 : number ->typeof (t1 ** t2 ** t1) : string +>typeof (t1 ** t2 ** t1) : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >(t1 ** t2 ** t1) : number >t1 ** t2 ** t1 : number >t1 : number diff --git a/tests/baselines/reference/emitExponentiationOperatorInTemplateString1ES6.types b/tests/baselines/reference/emitExponentiationOperatorInTemplateString1ES6.types index a005dd07463..0bc65c31b12 100644 --- a/tests/baselines/reference/emitExponentiationOperatorInTemplateString1ES6.types +++ b/tests/baselines/reference/emitExponentiationOperatorInTemplateString1ES6.types @@ -54,7 +54,7 @@ var s; `${typeof (t1 ** t2 ** t1) }`; >`${typeof (t1 ** t2 ** t1) }` : string ->typeof (t1 ** t2 ** t1) : string +>typeof (t1 ** t2 ** t1) : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >(t1 ** t2 ** t1) : number >t1 ** t2 ** t1 : number >t1 : number @@ -66,7 +66,7 @@ var s; >`${1 + typeof (t1 ** t2 ** t1) }` : string >1 + typeof (t1 ** t2 ** t1) : string >1 : 1 ->typeof (t1 ** t2 ** t1) : string +>typeof (t1 ** t2 ** t1) : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >(t1 ** t2 ** t1) : number >t1 ** t2 ** t1 : number >t1 : number @@ -141,14 +141,14 @@ var s; `${typeof (t1 ** t2 ** t1)}${typeof (t1 ** t2 ** t1)}`; >`${typeof (t1 ** t2 ** t1)}${typeof (t1 ** t2 ** t1)}` : string ->typeof (t1 ** t2 ** t1) : string +>typeof (t1 ** t2 ** t1) : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >(t1 ** t2 ** t1) : number >t1 ** t2 ** t1 : number >t1 : number >t2 ** t1 : number >t2 : number >t1 : number ->typeof (t1 ** t2 ** t1) : string +>typeof (t1 ** t2 ** t1) : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >(t1 ** t2 ** t1) : number >t1 ** t2 ** t1 : number >t1 : number @@ -223,14 +223,14 @@ var s; `${typeof (t1 ** t2 ** t1) } hello world ${typeof (t1 ** t2 ** t1) }`; >`${typeof (t1 ** t2 ** t1) } hello world ${typeof (t1 ** t2 ** t1) }` : string ->typeof (t1 ** t2 ** t1) : string +>typeof (t1 ** t2 ** t1) : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >(t1 ** t2 ** t1) : number >t1 ** t2 ** t1 : number >t1 : number >t2 ** t1 : number >t2 : number >t1 : number ->typeof (t1 ** t2 ** t1) : string +>typeof (t1 ** t2 ** t1) : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >(t1 ** t2 ** t1) : number >t1 ** t2 ** t1 : number >t1 : number diff --git a/tests/baselines/reference/emitExponentiationOperatorInTemplateString2.types b/tests/baselines/reference/emitExponentiationOperatorInTemplateString2.types index 156851b60b9..9b77f4bc3fc 100644 --- a/tests/baselines/reference/emitExponentiationOperatorInTemplateString2.types +++ b/tests/baselines/reference/emitExponentiationOperatorInTemplateString2.types @@ -54,7 +54,7 @@ var s; `hello ${typeof (t1 ** t2 ** t1) }`; >`hello ${typeof (t1 ** t2 ** t1) }` : string ->typeof (t1 ** t2 ** t1) : string +>typeof (t1 ** t2 ** t1) : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >(t1 ** t2 ** t1) : number >t1 ** t2 ** t1 : number >t1 : number @@ -66,7 +66,7 @@ var s; >`hello ${1 + typeof (t1 ** t2 ** t1) }` : string >1 + typeof (t1 ** t2 ** t1) : string >1 : 1 ->typeof (t1 ** t2 ** t1) : string +>typeof (t1 ** t2 ** t1) : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >(t1 ** t2 ** t1) : number >t1 ** t2 ** t1 : number >t1 : number @@ -141,14 +141,14 @@ var s; `hello ${typeof (t1 ** t2 ** t1) }${typeof (t1 ** t2 ** t1) }`; >`hello ${typeof (t1 ** t2 ** t1) }${typeof (t1 ** t2 ** t1) }` : string ->typeof (t1 ** t2 ** t1) : string +>typeof (t1 ** t2 ** t1) : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >(t1 ** t2 ** t1) : number >t1 ** t2 ** t1 : number >t1 : number >t2 ** t1 : number >t2 : number >t1 : number ->typeof (t1 ** t2 ** t1) : string +>typeof (t1 ** t2 ** t1) : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >(t1 ** t2 ** t1) : number >t1 ** t2 ** t1 : number >t1 : number @@ -223,14 +223,14 @@ var s; `hello ${typeof (t1 ** t2 ** t1) } hello world ${typeof (t1 ** t2 ** t1) }`; >`hello ${typeof (t1 ** t2 ** t1) } hello world ${typeof (t1 ** t2 ** t1) }` : string ->typeof (t1 ** t2 ** t1) : string +>typeof (t1 ** t2 ** t1) : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >(t1 ** t2 ** t1) : number >t1 ** t2 ** t1 : number >t1 : number >t2 ** t1 : number >t2 : number >t1 : number ->typeof (t1 ** t2 ** t1) : string +>typeof (t1 ** t2 ** t1) : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >(t1 ** t2 ** t1) : number >t1 ** t2 ** t1 : number >t1 : number diff --git a/tests/baselines/reference/emitExponentiationOperatorInTemplateString2ES6.types b/tests/baselines/reference/emitExponentiationOperatorInTemplateString2ES6.types index dbeee05554e..ed0be973e5b 100644 --- a/tests/baselines/reference/emitExponentiationOperatorInTemplateString2ES6.types +++ b/tests/baselines/reference/emitExponentiationOperatorInTemplateString2ES6.types @@ -54,7 +54,7 @@ var s; `hello ${typeof (t1 ** t2 ** t1) }`; >`hello ${typeof (t1 ** t2 ** t1) }` : string ->typeof (t1 ** t2 ** t1) : string +>typeof (t1 ** t2 ** t1) : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >(t1 ** t2 ** t1) : number >t1 ** t2 ** t1 : number >t1 : number @@ -66,7 +66,7 @@ var s; >`hello ${1 + typeof (t1 ** t2 ** t1) }` : string >1 + typeof (t1 ** t2 ** t1) : string >1 : 1 ->typeof (t1 ** t2 ** t1) : string +>typeof (t1 ** t2 ** t1) : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >(t1 ** t2 ** t1) : number >t1 ** t2 ** t1 : number >t1 : number @@ -141,14 +141,14 @@ var s; `hello ${typeof (t1 ** t2 ** t1) }${typeof (t1 ** t2 ** t1) }`; >`hello ${typeof (t1 ** t2 ** t1) }${typeof (t1 ** t2 ** t1) }` : string ->typeof (t1 ** t2 ** t1) : string +>typeof (t1 ** t2 ** t1) : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >(t1 ** t2 ** t1) : number >t1 ** t2 ** t1 : number >t1 : number >t2 ** t1 : number >t2 : number >t1 : number ->typeof (t1 ** t2 ** t1) : string +>typeof (t1 ** t2 ** t1) : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >(t1 ** t2 ** t1) : number >t1 ** t2 ** t1 : number >t1 : number @@ -223,14 +223,14 @@ var s; `hello ${typeof (t1 ** t2 ** t1) } hello world ${typeof (t1 ** t2 ** t1) }`; >`hello ${typeof (t1 ** t2 ** t1) } hello world ${typeof (t1 ** t2 ** t1) }` : string ->typeof (t1 ** t2 ** t1) : string +>typeof (t1 ** t2 ** t1) : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >(t1 ** t2 ** t1) : number >t1 ** t2 ** t1 : number >t1 : number >t2 ** t1 : number >t2 : number >t1 : number ->typeof (t1 ** t2 ** t1) : string +>typeof (t1 ** t2 ** t1) : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >(t1 ** t2 ** t1) : number >t1 ** t2 ** t1 : number >t1 : number diff --git a/tests/baselines/reference/emitExponentiationOperatorInTemplateString3.types b/tests/baselines/reference/emitExponentiationOperatorInTemplateString3.types index d3472beac12..16fe31dde5e 100644 --- a/tests/baselines/reference/emitExponentiationOperatorInTemplateString3.types +++ b/tests/baselines/reference/emitExponentiationOperatorInTemplateString3.types @@ -54,7 +54,7 @@ var s; `${typeof (t1 ** t2 ** t1) } world`; >`${typeof (t1 ** t2 ** t1) } world` : string ->typeof (t1 ** t2 ** t1) : string +>typeof (t1 ** t2 ** t1) : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >(t1 ** t2 ** t1) : number >t1 ** t2 ** t1 : number >t1 : number @@ -66,7 +66,7 @@ var s; >`${1 + typeof (t1 ** t2 ** t1) } world` : string >1 + typeof (t1 ** t2 ** t1) : string >1 : 1 ->typeof (t1 ** t2 ** t1) : string +>typeof (t1 ** t2 ** t1) : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >(t1 ** t2 ** t1) : number >t1 ** t2 ** t1 : number >t1 : number @@ -141,14 +141,14 @@ var s; `${typeof (t1 ** t2 ** t1) }${typeof (t1 ** t2 ** t1) } world`; >`${typeof (t1 ** t2 ** t1) }${typeof (t1 ** t2 ** t1) } world` : string ->typeof (t1 ** t2 ** t1) : string +>typeof (t1 ** t2 ** t1) : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >(t1 ** t2 ** t1) : number >t1 ** t2 ** t1 : number >t1 : number >t2 ** t1 : number >t2 : number >t1 : number ->typeof (t1 ** t2 ** t1) : string +>typeof (t1 ** t2 ** t1) : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >(t1 ** t2 ** t1) : number >t1 ** t2 ** t1 : number >t1 : number @@ -223,14 +223,14 @@ var s; `${typeof (t1 ** t2 ** t1) } hello world ${typeof (t1 ** t2 ** t1)} !!`; >`${typeof (t1 ** t2 ** t1) } hello world ${typeof (t1 ** t2 ** t1)} !!` : string ->typeof (t1 ** t2 ** t1) : string +>typeof (t1 ** t2 ** t1) : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >(t1 ** t2 ** t1) : number >t1 ** t2 ** t1 : number >t1 : number >t2 ** t1 : number >t2 : number >t1 : number ->typeof (t1 ** t2 ** t1) : string +>typeof (t1 ** t2 ** t1) : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >(t1 ** t2 ** t1) : number >t1 ** t2 ** t1 : number >t1 : number diff --git a/tests/baselines/reference/emitExponentiationOperatorInTemplateString3ES6.types b/tests/baselines/reference/emitExponentiationOperatorInTemplateString3ES6.types index 239ef02a529..86eb42efc05 100644 --- a/tests/baselines/reference/emitExponentiationOperatorInTemplateString3ES6.types +++ b/tests/baselines/reference/emitExponentiationOperatorInTemplateString3ES6.types @@ -54,7 +54,7 @@ var s; `${typeof (t1 ** t2 ** t1) } world`; >`${typeof (t1 ** t2 ** t1) } world` : string ->typeof (t1 ** t2 ** t1) : string +>typeof (t1 ** t2 ** t1) : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >(t1 ** t2 ** t1) : number >t1 ** t2 ** t1 : number >t1 : number @@ -66,7 +66,7 @@ var s; >`${1 + typeof (t1 ** t2 ** t1) } world` : string >1 + typeof (t1 ** t2 ** t1) : string >1 : 1 ->typeof (t1 ** t2 ** t1) : string +>typeof (t1 ** t2 ** t1) : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >(t1 ** t2 ** t1) : number >t1 ** t2 ** t1 : number >t1 : number @@ -141,14 +141,14 @@ var s; `${typeof (t1 ** t2 ** t1) }${typeof (t1 ** t2 ** t1) } world`; >`${typeof (t1 ** t2 ** t1) }${typeof (t1 ** t2 ** t1) } world` : string ->typeof (t1 ** t2 ** t1) : string +>typeof (t1 ** t2 ** t1) : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >(t1 ** t2 ** t1) : number >t1 ** t2 ** t1 : number >t1 : number >t2 ** t1 : number >t2 : number >t1 : number ->typeof (t1 ** t2 ** t1) : string +>typeof (t1 ** t2 ** t1) : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >(t1 ** t2 ** t1) : number >t1 ** t2 ** t1 : number >t1 : number @@ -223,14 +223,14 @@ var s; `${typeof (t1 ** t2 ** t1) } hello world ${typeof (t1 ** t2 ** t1)} !!`; >`${typeof (t1 ** t2 ** t1) } hello world ${typeof (t1 ** t2 ** t1)} !!` : string ->typeof (t1 ** t2 ** t1) : string +>typeof (t1 ** t2 ** t1) : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >(t1 ** t2 ** t1) : number >t1 ** t2 ** t1 : number >t1 : number >t2 ** t1 : number >t2 : number >t1 : number ->typeof (t1 ** t2 ** t1) : string +>typeof (t1 ** t2 ** t1) : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >(t1 ** t2 ** t1) : number >t1 ** t2 ** t1 : number >t1 : number diff --git a/tests/baselines/reference/interfaceDoesNotDependOnBaseTypes.types b/tests/baselines/reference/interfaceDoesNotDependOnBaseTypes.types index 4f60c5d36cc..eae55bc09d1 100644 --- a/tests/baselines/reference/interfaceDoesNotDependOnBaseTypes.types +++ b/tests/baselines/reference/interfaceDoesNotDependOnBaseTypes.types @@ -5,7 +5,7 @@ var x: StringTree; if (typeof x !== "string") { >typeof x !== "string" : boolean ->typeof x : string +>typeof x : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >x : StringTree >"string" : "string" diff --git a/tests/baselines/reference/mappedTypes4.types b/tests/baselines/reference/mappedTypes4.types index a2fec06ccec..1d0c4c16b89 100644 --- a/tests/baselines/reference/mappedTypes4.types +++ b/tests/baselines/reference/mappedTypes4.types @@ -29,7 +29,7 @@ function boxify(obj: T): Boxified { if (typeof obj === "object") { >typeof obj === "object" : boolean ->typeof obj : string +>typeof obj : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >obj : T >"object" : "object" diff --git a/tests/baselines/reference/narrowingConstrainedTypeParameter.types b/tests/baselines/reference/narrowingConstrainedTypeParameter.types index 942b9f7055d..348716ab3c4 100644 --- a/tests/baselines/reference/narrowingConstrainedTypeParameter.types +++ b/tests/baselines/reference/narrowingConstrainedTypeParameter.types @@ -17,7 +17,7 @@ function isPet(pet: any): pet is Pet { return typeof pet.name === "string"; >typeof pet.name === "string" : boolean ->typeof pet.name : string +>typeof pet.name : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >pet.name : any >pet : any >name : any diff --git a/tests/baselines/reference/nestedLoopTypeGuards.types b/tests/baselines/reference/nestedLoopTypeGuards.types index 9d7b793badf..e0279325012 100644 --- a/tests/baselines/reference/nestedLoopTypeGuards.types +++ b/tests/baselines/reference/nestedLoopTypeGuards.types @@ -9,7 +9,7 @@ function f1() { if (typeof a !== 'boolean') { >typeof a !== 'boolean' : boolean ->typeof a : string +>typeof a : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >a : string | number | boolean >'boolean' : "boolean" @@ -34,7 +34,7 @@ function f1() { if (typeof a === 'string') { >typeof a === 'string' : boolean ->typeof a : string +>typeof a : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >a : string | number >'string' : "string" @@ -66,7 +66,7 @@ function f2() { if (typeof a === 'string') { >typeof a === 'string' : boolean ->typeof a : string +>typeof a : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >a : string | number >'string' : "string" @@ -78,7 +78,7 @@ function f2() { if (typeof a === 'string') { >typeof a === 'string' : boolean ->typeof a : string +>typeof a : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >a : string >'string' : "string" diff --git a/tests/baselines/reference/neverType.types b/tests/baselines/reference/neverType.types index bdb1ff56c3e..9555285e4be 100644 --- a/tests/baselines/reference/neverType.types +++ b/tests/baselines/reference/neverType.types @@ -164,7 +164,7 @@ function f1(x: string | number) { if (typeof x === "boolean") { >typeof x === "boolean" : boolean ->typeof x : string +>typeof x : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >x : string | number >"boolean" : "boolean" @@ -182,7 +182,7 @@ function f2(x: string | number) { if (typeof x === "boolean") { >typeof x === "boolean" : boolean ->typeof x : string +>typeof x : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >x : string | number >"boolean" : "boolean" diff --git a/tests/baselines/reference/overloadResolutionOverNonCTLambdas.types b/tests/baselines/reference/overloadResolutionOverNonCTLambdas.types index ee5c336ba9c..a4de1666d0b 100644 --- a/tests/baselines/reference/overloadResolutionOverNonCTLambdas.types +++ b/tests/baselines/reference/overloadResolutionOverNonCTLambdas.types @@ -32,7 +32,7 @@ module Bugs { return typeof args[index] !== 'undefined' >typeof args[index] !== 'undefined' ? args[index] : match : any >typeof args[index] !== 'undefined' : boolean ->typeof args[index] : string +>typeof args[index] : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >args[index] : any >args : any[] >index : any diff --git a/tests/baselines/reference/overloadReturnTypes.types b/tests/baselines/reference/overloadReturnTypes.types index c0f573fb980..daf790b9a92 100644 --- a/tests/baselines/reference/overloadReturnTypes.types +++ b/tests/baselines/reference/overloadReturnTypes.types @@ -26,7 +26,7 @@ function attr(nameOrMap: any, value?: string): any { >nameOrMap && typeof nameOrMap === "object" : boolean >nameOrMap : any >typeof nameOrMap === "object" : boolean ->typeof nameOrMap : string +>typeof nameOrMap : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >nameOrMap : any >"object" : "object" diff --git a/tests/baselines/reference/prefixUnaryOperatorsOnExportedVariables.types b/tests/baselines/reference/prefixUnaryOperatorsOnExportedVariables.types index 4e4dbe93372..41df41af51b 100644 --- a/tests/baselines/reference/prefixUnaryOperatorsOnExportedVariables.types +++ b/tests/baselines/reference/prefixUnaryOperatorsOnExportedVariables.types @@ -39,7 +39,7 @@ if (void x) { } if (typeof x) { ->typeof x : string +>typeof x : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >x : false } diff --git a/tests/baselines/reference/symbolType17.types b/tests/baselines/reference/symbolType17.types index c186f915cd0..6ba36d335a7 100644 --- a/tests/baselines/reference/symbolType17.types +++ b/tests/baselines/reference/symbolType17.types @@ -12,7 +12,7 @@ x; if (typeof x === "symbol") { >typeof x === "symbol" : boolean ->typeof x : string +>typeof x : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >x : symbol | Foo >"symbol" : "symbol" diff --git a/tests/baselines/reference/symbolType18.types b/tests/baselines/reference/symbolType18.types index 8f0012f4f11..9c58320ed3b 100644 --- a/tests/baselines/reference/symbolType18.types +++ b/tests/baselines/reference/symbolType18.types @@ -12,7 +12,7 @@ x; if (typeof x === "object") { >typeof x === "object" : boolean ->typeof x : string +>typeof x : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >x : symbol | Foo >"object" : "object" diff --git a/tests/baselines/reference/symbolType19.types b/tests/baselines/reference/symbolType19.types index 18daa27fd00..66bd80b33d8 100644 --- a/tests/baselines/reference/symbolType19.types +++ b/tests/baselines/reference/symbolType19.types @@ -11,7 +11,7 @@ x; if (typeof x === "number") { >typeof x === "number" : boolean ->typeof x : string +>typeof x : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >x : symbol | E >"number" : "number" diff --git a/tests/baselines/reference/templateStringInTypeOf.types b/tests/baselines/reference/templateStringInTypeOf.types index 0d7d26a82b2..5de62164a70 100644 --- a/tests/baselines/reference/templateStringInTypeOf.types +++ b/tests/baselines/reference/templateStringInTypeOf.types @@ -1,7 +1,7 @@ === tests/cases/conformance/es6/templates/templateStringInTypeOf.ts === var x = typeof `abc${ 123 }def`; ->x : string ->typeof `abc${ 123 }def` : string +>x : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" +>typeof `abc${ 123 }def` : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >`abc${ 123 }def` : string >123 : 123 diff --git a/tests/baselines/reference/templateStringInTypeOfES6.types b/tests/baselines/reference/templateStringInTypeOfES6.types index ad142d13fe5..cc035a25501 100644 --- a/tests/baselines/reference/templateStringInTypeOfES6.types +++ b/tests/baselines/reference/templateStringInTypeOfES6.types @@ -1,7 +1,7 @@ === tests/cases/conformance/es6/templates/templateStringInTypeOfES6.ts === var x = typeof `abc${ 123 }def`; ->x : string ->typeof `abc${ 123 }def` : string +>x : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" +>typeof `abc${ 123 }def` : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >`abc${ 123 }def` : string >123 : 123 diff --git a/tests/baselines/reference/templateStringWithEmbeddedTypeOfOperator.types b/tests/baselines/reference/templateStringWithEmbeddedTypeOfOperator.types index 48330140ad3..a7811bd03bd 100644 --- a/tests/baselines/reference/templateStringWithEmbeddedTypeOfOperator.types +++ b/tests/baselines/reference/templateStringWithEmbeddedTypeOfOperator.types @@ -2,6 +2,6 @@ var x = `abc${ typeof "hi" }def`; >x : string >`abc${ typeof "hi" }def` : string ->typeof "hi" : string +>typeof "hi" : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >"hi" : "hi" diff --git a/tests/baselines/reference/templateStringWithEmbeddedTypeOfOperatorES6.types b/tests/baselines/reference/templateStringWithEmbeddedTypeOfOperatorES6.types index 3d7eba45c19..27e593bf4b3 100644 --- a/tests/baselines/reference/templateStringWithEmbeddedTypeOfOperatorES6.types +++ b/tests/baselines/reference/templateStringWithEmbeddedTypeOfOperatorES6.types @@ -2,6 +2,6 @@ var x = `abc${ typeof "hi" }def`; >x : string >`abc${ typeof "hi" }def` : string ->typeof "hi" : string +>typeof "hi" : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >"hi" : "hi" diff --git a/tests/baselines/reference/throwStatements.types b/tests/baselines/reference/throwStatements.types index 19b8988ed47..3c8fd64ee39 100644 --- a/tests/baselines/reference/throwStatements.types +++ b/tests/baselines/reference/throwStatements.types @@ -174,7 +174,7 @@ throw aModule; >aModule : typeof M throw typeof M; ->typeof M : string +>typeof M : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >M : typeof M var aClassInModule = new M.A(); diff --git a/tests/baselines/reference/typeGuardEnums.types b/tests/baselines/reference/typeGuardEnums.types index f9d5cb1754e..cf62bccebd3 100644 --- a/tests/baselines/reference/typeGuardEnums.types +++ b/tests/baselines/reference/typeGuardEnums.types @@ -12,7 +12,7 @@ let x: number|string|E|V; if (typeof x === "number") { >typeof x === "number" : boolean ->typeof x : string +>typeof x : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >x : string | number | E | V >"number" : "number" @@ -26,7 +26,7 @@ else { if (typeof x !== "number") { >typeof x !== "number" : boolean ->typeof x : string +>typeof x : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >x : string | number | E | V >"number" : "number" diff --git a/tests/baselines/reference/typeGuardIntersectionTypes.types b/tests/baselines/reference/typeGuardIntersectionTypes.types index 6b6dbae8ca2..b6206ed2007 100644 --- a/tests/baselines/reference/typeGuardIntersectionTypes.types +++ b/tests/baselines/reference/typeGuardIntersectionTypes.types @@ -163,7 +163,7 @@ function hasLegs(x: Beast): x is Legged { return x && typeof x.legs === 'number' >x && typeof x.legs === 'number' : boolean >x : Beast >typeof x.legs === 'number' : boolean ->typeof x.legs : string +>typeof x.legs : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >x.legs : number | undefined >x : Beast >legs : number | undefined diff --git a/tests/baselines/reference/typeGuardNesting.types b/tests/baselines/reference/typeGuardNesting.types index 29f6cba10db..c1396130c05 100644 --- a/tests/baselines/reference/typeGuardNesting.types +++ b/tests/baselines/reference/typeGuardNesting.types @@ -7,13 +7,13 @@ if ((typeof strOrBool === 'boolean' && !strOrBool) || typeof strOrBool === 'stri >(typeof strOrBool === 'boolean' && !strOrBool) : boolean >typeof strOrBool === 'boolean' && !strOrBool : boolean >typeof strOrBool === 'boolean' : boolean ->typeof strOrBool : string +>typeof strOrBool : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >strOrBool : string | boolean >'boolean' : "boolean" >!strOrBool : boolean >strOrBool : boolean >typeof strOrBool === 'string' : boolean ->typeof strOrBool : string +>typeof strOrBool : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >strOrBool : string | true >'string' : "string" @@ -22,7 +22,7 @@ if ((typeof strOrBool === 'boolean' && !strOrBool) || typeof strOrBool === 'stri >(typeof strOrBool === 'string') ? strOrBool : "string" : string >(typeof strOrBool === 'string') : boolean >typeof strOrBool === 'string' : boolean ->typeof strOrBool : string +>typeof strOrBool : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >strOrBool : string | boolean >'string' : "string" >strOrBool : string @@ -33,7 +33,7 @@ if ((typeof strOrBool === 'boolean' && !strOrBool) || typeof strOrBool === 'stri >(typeof strOrBool === 'boolean') ? strOrBool : false : boolean >(typeof strOrBool === 'boolean') : boolean >typeof strOrBool === 'boolean' : boolean ->typeof strOrBool : string +>typeof strOrBool : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >strOrBool : string | boolean >'boolean' : "boolean" >strOrBool : boolean @@ -44,7 +44,7 @@ if ((typeof strOrBool === 'boolean' && !strOrBool) || typeof strOrBool === 'stri >(typeof strOrBool !== 'boolean') ? strOrBool : "string" : string >(typeof strOrBool !== 'boolean') : boolean >typeof strOrBool !== 'boolean' : boolean ->typeof strOrBool : string +>typeof strOrBool : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >strOrBool : string | boolean >'boolean' : "boolean" >strOrBool : string @@ -55,7 +55,7 @@ if ((typeof strOrBool === 'boolean' && !strOrBool) || typeof strOrBool === 'stri >(typeof strOrBool !== 'string') ? strOrBool : false : boolean >(typeof strOrBool !== 'string') : boolean >typeof strOrBool !== 'string' : boolean ->typeof strOrBool : string +>typeof strOrBool : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >strOrBool : string | boolean >'string' : "string" >strOrBool : boolean @@ -67,13 +67,13 @@ if ((typeof strOrBool !== 'string' && !strOrBool) || typeof strOrBool !== 'boole >(typeof strOrBool !== 'string' && !strOrBool) : boolean >typeof strOrBool !== 'string' && !strOrBool : boolean >typeof strOrBool !== 'string' : boolean ->typeof strOrBool : string +>typeof strOrBool : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >strOrBool : string | boolean >'string' : "string" >!strOrBool : boolean >strOrBool : boolean >typeof strOrBool !== 'boolean' : boolean ->typeof strOrBool : string +>typeof strOrBool : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >strOrBool : string | true >'boolean' : "boolean" @@ -82,7 +82,7 @@ if ((typeof strOrBool !== 'string' && !strOrBool) || typeof strOrBool !== 'boole >(typeof strOrBool === 'string') ? strOrBool : "string" : string >(typeof strOrBool === 'string') : boolean >typeof strOrBool === 'string' : boolean ->typeof strOrBool : string +>typeof strOrBool : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >strOrBool : string | boolean >'string' : "string" >strOrBool : string @@ -93,7 +93,7 @@ if ((typeof strOrBool !== 'string' && !strOrBool) || typeof strOrBool !== 'boole >(typeof strOrBool === 'boolean') ? strOrBool : false : boolean >(typeof strOrBool === 'boolean') : boolean >typeof strOrBool === 'boolean' : boolean ->typeof strOrBool : string +>typeof strOrBool : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >strOrBool : string | boolean >'boolean' : "boolean" >strOrBool : boolean @@ -104,7 +104,7 @@ if ((typeof strOrBool !== 'string' && !strOrBool) || typeof strOrBool !== 'boole >(typeof strOrBool !== 'boolean') ? strOrBool : "string" : string >(typeof strOrBool !== 'boolean') : boolean >typeof strOrBool !== 'boolean' : boolean ->typeof strOrBool : string +>typeof strOrBool : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >strOrBool : string | boolean >'boolean' : "boolean" >strOrBool : string @@ -115,7 +115,7 @@ if ((typeof strOrBool !== 'string' && !strOrBool) || typeof strOrBool !== 'boole >(typeof strOrBool !== 'string') ? strOrBool : false : boolean >(typeof strOrBool !== 'string') : boolean >typeof strOrBool !== 'string' : boolean ->typeof strOrBool : string +>typeof strOrBool : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >strOrBool : string | boolean >'string' : "string" >strOrBool : boolean diff --git a/tests/baselines/reference/typeGuardOfFormExpr1AndExpr2.types b/tests/baselines/reference/typeGuardOfFormExpr1AndExpr2.types index b24b63f61dc..78d419d7dcd 100644 --- a/tests/baselines/reference/typeGuardOfFormExpr1AndExpr2.types +++ b/tests/baselines/reference/typeGuardOfFormExpr1AndExpr2.types @@ -42,11 +42,11 @@ var strOrNumOrBoolOrC: string | number | boolean | C; if (typeof strOrNumOrBool !== "string" && typeof strOrNumOrBool !== "number") { >typeof strOrNumOrBool !== "string" && typeof strOrNumOrBool !== "number" : boolean >typeof strOrNumOrBool !== "string" : boolean ->typeof strOrNumOrBool : string +>typeof strOrNumOrBool : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >strOrNumOrBool : string | number | boolean >"string" : "string" >typeof strOrNumOrBool !== "number" : boolean ->typeof strOrNumOrBool : string +>typeof strOrNumOrBool : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >strOrNumOrBool : number | boolean >"number" : "number" @@ -66,15 +66,15 @@ if (typeof strOrNumOrBoolOrC !== "string" && typeof strOrNumOrBoolOrC !== "numbe >typeof strOrNumOrBoolOrC !== "string" && typeof strOrNumOrBoolOrC !== "number" && typeof strOrNumOrBoolOrC !== "boolean" : boolean >typeof strOrNumOrBoolOrC !== "string" && typeof strOrNumOrBoolOrC !== "number" : boolean >typeof strOrNumOrBoolOrC !== "string" : boolean ->typeof strOrNumOrBoolOrC : string +>typeof strOrNumOrBoolOrC : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >strOrNumOrBoolOrC : string | number | boolean | C >"string" : "string" >typeof strOrNumOrBoolOrC !== "number" : boolean ->typeof strOrNumOrBoolOrC : string +>typeof strOrNumOrBoolOrC : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >strOrNumOrBoolOrC : number | boolean | C >"number" : "number" >typeof strOrNumOrBoolOrC !== "boolean" : boolean ->typeof strOrNumOrBoolOrC : string +>typeof strOrNumOrBoolOrC : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >strOrNumOrBoolOrC : boolean | C >"boolean" : "boolean" @@ -94,15 +94,15 @@ if (typeof strOrNumOrBoolOrC !== "string" && typeof strOrNumOrBoolOrC !== "numbe >typeof strOrNumOrBoolOrC !== "string" && typeof strOrNumOrBoolOrC !== "number" && typeof strOrNumOrBool === "boolean" : boolean >typeof strOrNumOrBoolOrC !== "string" && typeof strOrNumOrBoolOrC !== "number" : boolean >typeof strOrNumOrBoolOrC !== "string" : boolean ->typeof strOrNumOrBoolOrC : string +>typeof strOrNumOrBoolOrC : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >strOrNumOrBoolOrC : string | number | boolean | C >"string" : "string" >typeof strOrNumOrBoolOrC !== "number" : boolean ->typeof strOrNumOrBoolOrC : string +>typeof strOrNumOrBoolOrC : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >strOrNumOrBoolOrC : number | boolean | C >"number" : "number" >typeof strOrNumOrBool === "boolean" : boolean ->typeof strOrNumOrBool : string +>typeof strOrNumOrBool : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >strOrNumOrBool : string | number | boolean >"boolean" : "boolean" @@ -130,7 +130,7 @@ else { if (typeof strOrNumOrBool !== "string" && numOrBool !== strOrNumOrBool) { >typeof strOrNumOrBool !== "string" && numOrBool !== strOrNumOrBool : boolean >typeof strOrNumOrBool !== "string" : boolean ->typeof strOrNumOrBool : string +>typeof strOrNumOrBool : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >strOrNumOrBool : string | number | boolean >"string" : "string" >numOrBool !== strOrNumOrBool : boolean diff --git a/tests/baselines/reference/typeGuardOfFormExpr1OrExpr2.types b/tests/baselines/reference/typeGuardOfFormExpr1OrExpr2.types index eb428bcb679..e2a06a817af 100644 --- a/tests/baselines/reference/typeGuardOfFormExpr1OrExpr2.types +++ b/tests/baselines/reference/typeGuardOfFormExpr1OrExpr2.types @@ -42,11 +42,11 @@ var strOrNumOrBoolOrC: string | number | boolean | C; if (typeof strOrNumOrBool === "string" || typeof strOrNumOrBool === "number") { >typeof strOrNumOrBool === "string" || typeof strOrNumOrBool === "number" : boolean >typeof strOrNumOrBool === "string" : boolean ->typeof strOrNumOrBool : string +>typeof strOrNumOrBool : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >strOrNumOrBool : string | number | boolean >"string" : "string" >typeof strOrNumOrBool === "number" : boolean ->typeof strOrNumOrBool : string +>typeof strOrNumOrBool : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >strOrNumOrBool : number | boolean >"number" : "number" @@ -66,15 +66,15 @@ if (typeof strOrNumOrBoolOrC === "string" || typeof strOrNumOrBoolOrC === "numbe >typeof strOrNumOrBoolOrC === "string" || typeof strOrNumOrBoolOrC === "number" || typeof strOrNumOrBoolOrC === "boolean" : boolean >typeof strOrNumOrBoolOrC === "string" || typeof strOrNumOrBoolOrC === "number" : boolean >typeof strOrNumOrBoolOrC === "string" : boolean ->typeof strOrNumOrBoolOrC : string +>typeof strOrNumOrBoolOrC : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >strOrNumOrBoolOrC : string | number | boolean | C >"string" : "string" >typeof strOrNumOrBoolOrC === "number" : boolean ->typeof strOrNumOrBoolOrC : string +>typeof strOrNumOrBoolOrC : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >strOrNumOrBoolOrC : number | boolean | C >"number" : "number" >typeof strOrNumOrBoolOrC === "boolean" : boolean ->typeof strOrNumOrBoolOrC : string +>typeof strOrNumOrBoolOrC : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >strOrNumOrBoolOrC : boolean | C >"boolean" : "boolean" @@ -94,15 +94,15 @@ if (typeof strOrNumOrBoolOrC === "string" || typeof strOrNumOrBoolOrC === "numbe >typeof strOrNumOrBoolOrC === "string" || typeof strOrNumOrBoolOrC === "number" || typeof strOrNumOrBool !== "boolean" : boolean >typeof strOrNumOrBoolOrC === "string" || typeof strOrNumOrBoolOrC === "number" : boolean >typeof strOrNumOrBoolOrC === "string" : boolean ->typeof strOrNumOrBoolOrC : string +>typeof strOrNumOrBoolOrC : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >strOrNumOrBoolOrC : string | number | boolean | C >"string" : "string" >typeof strOrNumOrBoolOrC === "number" : boolean ->typeof strOrNumOrBoolOrC : string +>typeof strOrNumOrBoolOrC : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >strOrNumOrBoolOrC : number | boolean | C >"number" : "number" >typeof strOrNumOrBool !== "boolean" : boolean ->typeof strOrNumOrBool : string +>typeof strOrNumOrBool : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >strOrNumOrBool : string | number | boolean >"boolean" : "boolean" @@ -130,7 +130,7 @@ else { if (typeof strOrNumOrBool === "string" || numOrBool !== strOrNumOrBool) { >typeof strOrNumOrBool === "string" || numOrBool !== strOrNumOrBool : boolean >typeof strOrNumOrBool === "string" : boolean ->typeof strOrNumOrBool : string +>typeof strOrNumOrBool : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >strOrNumOrBool : string | number | boolean >"string" : "string" >numOrBool !== strOrNumOrBool : boolean diff --git a/tests/baselines/reference/typeGuardOfFormNotExpr.types b/tests/baselines/reference/typeGuardOfFormNotExpr.types index e4490d42dae..624bd7c71fc 100644 --- a/tests/baselines/reference/typeGuardOfFormNotExpr.types +++ b/tests/baselines/reference/typeGuardOfFormNotExpr.types @@ -26,7 +26,7 @@ if (!(typeof strOrNum === "string")) { >!(typeof strOrNum === "string") : boolean >(typeof strOrNum === "string") : boolean >typeof strOrNum === "string" : boolean ->typeof strOrNum : string +>typeof strOrNum : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >strOrNum : string | number >"string" : "string" @@ -47,11 +47,11 @@ if (!(typeof strOrNumOrBool === "string" || typeof strOrNumOrBool === "number")) >(typeof strOrNumOrBool === "string" || typeof strOrNumOrBool === "number") : boolean >typeof strOrNumOrBool === "string" || typeof strOrNumOrBool === "number" : boolean >typeof strOrNumOrBool === "string" : boolean ->typeof strOrNumOrBool : string +>typeof strOrNumOrBool : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >strOrNumOrBool : string | number | boolean >"string" : "string" >typeof strOrNumOrBool === "number" : boolean ->typeof strOrNumOrBool : string +>typeof strOrNumOrBool : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >strOrNumOrBool : number | boolean >"number" : "number" @@ -72,13 +72,13 @@ if (!(typeof strOrNumOrBool !== "string") || !(typeof strOrNumOrBool !== "number >!(typeof strOrNumOrBool !== "string") : boolean >(typeof strOrNumOrBool !== "string") : boolean >typeof strOrNumOrBool !== "string" : boolean ->typeof strOrNumOrBool : string +>typeof strOrNumOrBool : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >strOrNumOrBool : string | number | boolean >"string" : "string" >!(typeof strOrNumOrBool !== "number") : boolean >(typeof strOrNumOrBool !== "number") : boolean >typeof strOrNumOrBool !== "number" : boolean ->typeof strOrNumOrBool : string +>typeof strOrNumOrBool : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >strOrNumOrBool : number | boolean >"number" : "number" @@ -99,11 +99,11 @@ if (!(typeof strOrNumOrBool !== "string" && typeof strOrNumOrBool !== "number")) >(typeof strOrNumOrBool !== "string" && typeof strOrNumOrBool !== "number") : boolean >typeof strOrNumOrBool !== "string" && typeof strOrNumOrBool !== "number" : boolean >typeof strOrNumOrBool !== "string" : boolean ->typeof strOrNumOrBool : string +>typeof strOrNumOrBool : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >strOrNumOrBool : string | number | boolean >"string" : "string" >typeof strOrNumOrBool !== "number" : boolean ->typeof strOrNumOrBool : string +>typeof strOrNumOrBool : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >strOrNumOrBool : number | boolean >"number" : "number" @@ -124,13 +124,13 @@ if (!(typeof strOrNumOrBool === "string") && !(typeof strOrNumOrBool === "number >!(typeof strOrNumOrBool === "string") : boolean >(typeof strOrNumOrBool === "string") : boolean >typeof strOrNumOrBool === "string" : boolean ->typeof strOrNumOrBool : string +>typeof strOrNumOrBool : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >strOrNumOrBool : string | number | boolean >"string" : "string" >!(typeof strOrNumOrBool === "number") : boolean >(typeof strOrNumOrBool === "number") : boolean >typeof strOrNumOrBool === "number" : boolean ->typeof strOrNumOrBool : string +>typeof strOrNumOrBool : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >strOrNumOrBool : number | boolean >"number" : "number" @@ -151,7 +151,7 @@ if (!(typeof strOrNumOrBool === "string") && numOrBool !== strOrNumOrBool) { >!(typeof strOrNumOrBool === "string") : boolean >(typeof strOrNumOrBool === "string") : boolean >typeof strOrNumOrBool === "string" : boolean ->typeof strOrNumOrBool : string +>typeof strOrNumOrBool : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >strOrNumOrBool : string | number | boolean >"string" : "string" >numOrBool !== strOrNumOrBool : boolean diff --git a/tests/baselines/reference/typeGuardOfFormTypeOfBoolean.types b/tests/baselines/reference/typeGuardOfFormTypeOfBoolean.types index c06c16e331d..a2cfdf64ea8 100644 --- a/tests/baselines/reference/typeGuardOfFormTypeOfBoolean.types +++ b/tests/baselines/reference/typeGuardOfFormTypeOfBoolean.types @@ -46,7 +46,7 @@ var c: C; // - when false, removes the primitive type from the type of x. if (typeof strOrBool === "boolean") { >typeof strOrBool === "boolean" : boolean ->typeof strOrBool : string +>typeof strOrBool : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >strOrBool : string | boolean >"boolean" : "boolean" @@ -63,7 +63,7 @@ else { } if (typeof numOrBool === "boolean") { >typeof numOrBool === "boolean" : boolean ->typeof numOrBool : string +>typeof numOrBool : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >numOrBool : number | boolean >"boolean" : "boolean" @@ -80,7 +80,7 @@ else { } if (typeof strOrNumOrBool === "boolean") { >typeof strOrNumOrBool === "boolean" : boolean ->typeof strOrNumOrBool : string +>typeof strOrNumOrBool : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >strOrNumOrBool : string | number | boolean >"boolean" : "boolean" @@ -97,7 +97,7 @@ else { } if (typeof boolOrC === "boolean") { >typeof boolOrC === "boolean" : boolean ->typeof boolOrC : string +>typeof boolOrC : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >boolOrC : boolean | C >"boolean" : "boolean" @@ -115,7 +115,7 @@ else { if (typeof strOrNum === "boolean") { >typeof strOrNum === "boolean" : boolean ->typeof strOrNum : string +>typeof strOrNum : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >strOrNum : string | number >"boolean" : "boolean" @@ -135,7 +135,7 @@ else { // - when false, narrows the type of x by typeof x === s when true. if (typeof strOrBool !== "boolean") { >typeof strOrBool !== "boolean" : boolean ->typeof strOrBool : string +>typeof strOrBool : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >strOrBool : string | boolean >"boolean" : "boolean" @@ -152,7 +152,7 @@ else { } if (typeof numOrBool !== "boolean") { >typeof numOrBool !== "boolean" : boolean ->typeof numOrBool : string +>typeof numOrBool : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >numOrBool : number | boolean >"boolean" : "boolean" @@ -169,7 +169,7 @@ else { } if (typeof strOrNumOrBool !== "boolean") { >typeof strOrNumOrBool !== "boolean" : boolean ->typeof strOrNumOrBool : string +>typeof strOrNumOrBool : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >strOrNumOrBool : string | number | boolean >"boolean" : "boolean" @@ -186,7 +186,7 @@ else { } if (typeof boolOrC !== "boolean") { >typeof boolOrC !== "boolean" : boolean ->typeof boolOrC : string +>typeof boolOrC : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >boolOrC : boolean | C >"boolean" : "boolean" @@ -204,7 +204,7 @@ else { if (typeof strOrNum !== "boolean") { >typeof strOrNum !== "boolean" : boolean ->typeof strOrNum : string +>typeof strOrNum : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >strOrNum : string | number >"boolean" : "boolean" diff --git a/tests/baselines/reference/typeGuardOfFormTypeOfEqualEqualHasNoEffect.errors.txt b/tests/baselines/reference/typeGuardOfFormTypeOfEqualEqualHasNoEffect.errors.txt index c76c6e819df..1845d2e9775 100644 --- a/tests/baselines/reference/typeGuardOfFormTypeOfEqualEqualHasNoEffect.errors.txt +++ b/tests/baselines/reference/typeGuardOfFormTypeOfEqualEqualHasNoEffect.errors.txt @@ -1,10 +1,11 @@ tests/cases/conformance/expressions/typeGuards/typeGuardOfFormTypeOfEqualEqualHasNoEffect.ts(13,9): error TS2403: Subsequent variable declarations must have the same type. Variable 'r1' must be of type 'string', but here has type 'number'. tests/cases/conformance/expressions/typeGuards/typeGuardOfFormTypeOfEqualEqualHasNoEffect.ts(20,9): error TS2403: Subsequent variable declarations must have the same type. Variable 'r2' must be of type 'boolean', but here has type 'string'. tests/cases/conformance/expressions/typeGuards/typeGuardOfFormTypeOfEqualEqualHasNoEffect.ts(27,9): error TS2403: Subsequent variable declarations must have the same type. Variable 'r3' must be of type 'number', but here has type 'boolean'. +tests/cases/conformance/expressions/typeGuards/typeGuardOfFormTypeOfEqualEqualHasNoEffect.ts(30,5): error TS2365: Operator '==' cannot be applied to types '"string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function"' and '"Object"'. tests/cases/conformance/expressions/typeGuards/typeGuardOfFormTypeOfEqualEqualHasNoEffect.ts(34,9): error TS2403: Subsequent variable declarations must have the same type. Variable 'r4' must be of type 'C', but here has type 'string'. -==== tests/cases/conformance/expressions/typeGuards/typeGuardOfFormTypeOfEqualEqualHasNoEffect.ts (4 errors) ==== +==== tests/cases/conformance/expressions/typeGuards/typeGuardOfFormTypeOfEqualEqualHasNoEffect.ts (5 errors) ==== class C { private p: string }; var strOrNum: string | number; @@ -41,6 +42,8 @@ tests/cases/conformance/expressions/typeGuards/typeGuardOfFormTypeOfEqualEqualHa } if (typeof strOrC == "Object") { + ~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2365: Operator '==' cannot be applied to types '"string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function"' and '"Object"'. var r4 = strOrC; // string | C } else { diff --git a/tests/baselines/reference/typeGuardOfFormTypeOfIsOrderIndependent.types b/tests/baselines/reference/typeGuardOfFormTypeOfIsOrderIndependent.types index 43cc37f98e8..be594983779 100644 --- a/tests/baselines/reference/typeGuardOfFormTypeOfIsOrderIndependent.types +++ b/tests/baselines/reference/typeGuardOfFormTypeOfIsOrderIndependent.types @@ -26,7 +26,7 @@ var func: () => void; if ("string" === typeof strOrNum) { >"string" === typeof strOrNum : boolean >"string" : "string" ->typeof strOrNum : string +>typeof strOrNum : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >strOrNum : string | number str = strOrNum; @@ -43,7 +43,7 @@ else { if ("function" === typeof strOrFunc) { >"function" === typeof strOrFunc : boolean >"function" : "function" ->typeof strOrFunc : string +>typeof strOrFunc : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >strOrFunc : string | (() => void) func = strOrFunc; @@ -60,7 +60,7 @@ else { if ("number" === typeof numOrBool) { >"number" === typeof numOrBool : boolean >"number" : "number" ->typeof numOrBool : string +>typeof numOrBool : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >numOrBool : number | boolean num = numOrBool; @@ -77,7 +77,7 @@ else { if ("boolean" === typeof strOrBool) { >"boolean" === typeof strOrBool : boolean >"boolean" : "boolean" ->typeof strOrBool : string +>typeof strOrBool : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >strOrBool : string | boolean bool = strOrBool; diff --git a/tests/baselines/reference/typeGuardOfFormTypeOfNotEqualHasNoEffect.errors.txt b/tests/baselines/reference/typeGuardOfFormTypeOfNotEqualHasNoEffect.errors.txt index 3b29f3ecba8..1814abec823 100644 --- a/tests/baselines/reference/typeGuardOfFormTypeOfNotEqualHasNoEffect.errors.txt +++ b/tests/baselines/reference/typeGuardOfFormTypeOfNotEqualHasNoEffect.errors.txt @@ -1,10 +1,11 @@ tests/cases/conformance/expressions/typeGuards/typeGuardOfFormTypeOfNotEqualHasNoEffect.ts(13,9): error TS2403: Subsequent variable declarations must have the same type. Variable 'r1' must be of type 'number', but here has type 'string'. tests/cases/conformance/expressions/typeGuards/typeGuardOfFormTypeOfNotEqualHasNoEffect.ts(20,9): error TS2403: Subsequent variable declarations must have the same type. Variable 'r2' must be of type 'string', but here has type 'boolean'. tests/cases/conformance/expressions/typeGuards/typeGuardOfFormTypeOfNotEqualHasNoEffect.ts(27,9): error TS2403: Subsequent variable declarations must have the same type. Variable 'r3' must be of type 'boolean', but here has type 'number'. +tests/cases/conformance/expressions/typeGuards/typeGuardOfFormTypeOfNotEqualHasNoEffect.ts(30,5): error TS2365: Operator '!=' cannot be applied to types '"string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function"' and '"Object"'. tests/cases/conformance/expressions/typeGuards/typeGuardOfFormTypeOfNotEqualHasNoEffect.ts(34,9): error TS2403: Subsequent variable declarations must have the same type. Variable 'r4' must be of type 'string', but here has type 'C'. -==== tests/cases/conformance/expressions/typeGuards/typeGuardOfFormTypeOfNotEqualHasNoEffect.ts (4 errors) ==== +==== tests/cases/conformance/expressions/typeGuards/typeGuardOfFormTypeOfNotEqualHasNoEffect.ts (5 errors) ==== class C { private p: string }; var strOrNum: string | number; @@ -41,6 +42,8 @@ tests/cases/conformance/expressions/typeGuards/typeGuardOfFormTypeOfNotEqualHasN } if (typeof strOrC != "Object") { + ~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2365: Operator '!=' cannot be applied to types '"string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function"' and '"Object"'. var r4 = strOrC; // string | C } else { diff --git a/tests/baselines/reference/typeGuardOfFormTypeOfNumber.types b/tests/baselines/reference/typeGuardOfFormTypeOfNumber.types index 17787d06486..ec0854f6bc2 100644 --- a/tests/baselines/reference/typeGuardOfFormTypeOfNumber.types +++ b/tests/baselines/reference/typeGuardOfFormTypeOfNumber.types @@ -46,7 +46,7 @@ var c: C; // - when false, removes the primitive type from the type of x. if (typeof strOrNum === "number") { >typeof strOrNum === "number" : boolean ->typeof strOrNum : string +>typeof strOrNum : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >strOrNum : string | number >"number" : "number" @@ -63,7 +63,7 @@ else { } if (typeof numOrBool === "number") { >typeof numOrBool === "number" : boolean ->typeof numOrBool : string +>typeof numOrBool : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >numOrBool : number | boolean >"number" : "number" @@ -79,7 +79,7 @@ else { } if (typeof strOrNumOrBool === "number") { >typeof strOrNumOrBool === "number" : boolean ->typeof strOrNumOrBool : string +>typeof strOrNumOrBool : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >strOrNumOrBool : string | number | boolean >"number" : "number" @@ -96,7 +96,7 @@ else { } if (typeof numOrC === "number") { >typeof numOrC === "number" : boolean ->typeof numOrC : string +>typeof numOrC : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >numOrC : number | C >"number" : "number" @@ -114,7 +114,7 @@ else { if (typeof strOrBool === "number") { >typeof strOrBool === "number" : boolean ->typeof strOrBool : string +>typeof strOrBool : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >strOrBool : string | boolean >"number" : "number" @@ -133,7 +133,7 @@ else { // - when false, narrows the type of x by typeof x === s when true. if (typeof strOrNum !== "number") { >typeof strOrNum !== "number" : boolean ->typeof strOrNum : string +>typeof strOrNum : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >strOrNum : string | number >"number" : "number" @@ -150,7 +150,7 @@ else { } if (typeof numOrBool !== "number") { >typeof numOrBool !== "number" : boolean ->typeof numOrBool : string +>typeof numOrBool : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >numOrBool : number | boolean >"number" : "number" @@ -166,7 +166,7 @@ else { } if (typeof strOrNumOrBool !== "number") { >typeof strOrNumOrBool !== "number" : boolean ->typeof strOrNumOrBool : string +>typeof strOrNumOrBool : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >strOrNumOrBool : string | number | boolean >"number" : "number" @@ -183,7 +183,7 @@ else { } if (typeof numOrC !== "number") { >typeof numOrC !== "number" : boolean ->typeof numOrC : string +>typeof numOrC : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >numOrC : number | C >"number" : "number" @@ -201,7 +201,7 @@ else { if (typeof strOrBool !== "number") { >typeof strOrBool !== "number" : boolean ->typeof strOrBool : string +>typeof strOrBool : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >strOrBool : string | boolean >"number" : "number" diff --git a/tests/baselines/reference/typeGuardOfFormTypeOfOther.errors.txt b/tests/baselines/reference/typeGuardOfFormTypeOfOther.errors.txt new file mode 100644 index 00000000000..c9cb9fdd456 --- /dev/null +++ b/tests/baselines/reference/typeGuardOfFormTypeOfOther.errors.txt @@ -0,0 +1,118 @@ +tests/cases/conformance/expressions/typeGuards/typeGuardOfFormTypeOfOther.ts(21,5): error TS2365: Operator '===' cannot be applied to types '"string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function"' and '"Object"'. +tests/cases/conformance/expressions/typeGuards/typeGuardOfFormTypeOfOther.ts(27,5): error TS2365: Operator '===' cannot be applied to types '"string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function"' and '"Object"'. +tests/cases/conformance/expressions/typeGuards/typeGuardOfFormTypeOfOther.ts(33,5): error TS2365: Operator '===' cannot be applied to types '"string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function"' and '"Object"'. +tests/cases/conformance/expressions/typeGuards/typeGuardOfFormTypeOfOther.ts(40,5): error TS2322: Type 'string | C' is not assignable to type 'C'. + Type 'string' is not assignable to type 'C'. +tests/cases/conformance/expressions/typeGuards/typeGuardOfFormTypeOfOther.ts(43,9): error TS2322: Type 'string | C' is not assignable to type 'string'. + Type 'C' is not assignable to type 'string'. +tests/cases/conformance/expressions/typeGuards/typeGuardOfFormTypeOfOther.ts(46,5): error TS2365: Operator '===' cannot be applied to types '"string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function"' and '"Object"'. +tests/cases/conformance/expressions/typeGuards/typeGuardOfFormTypeOfOther.ts(56,5): error TS2365: Operator '!==' cannot be applied to types '"string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function"' and '"Object"'. +tests/cases/conformance/expressions/typeGuards/typeGuardOfFormTypeOfOther.ts(62,5): error TS2365: Operator '!==' cannot be applied to types '"string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function"' and '"Object"'. +tests/cases/conformance/expressions/typeGuards/typeGuardOfFormTypeOfOther.ts(68,5): error TS2365: Operator '!==' cannot be applied to types '"string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function"' and '"Object"'. +tests/cases/conformance/expressions/typeGuards/typeGuardOfFormTypeOfOther.ts(75,5): error TS2365: Operator '!==' cannot be applied to types '"string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function"' and '"Object"'. + + +==== tests/cases/conformance/expressions/typeGuards/typeGuardOfFormTypeOfOther.ts (10 errors) ==== + class C { private p: string }; + + var str: string; + var bool: boolean; + var num: number; + var strOrNum: string | number; + var strOrBool: string | boolean; + var numOrBool: number | boolean + var strOrNumOrBool: string | number | boolean; + var strOrC: string | C; + var numOrC: number | C; + var boolOrC: boolean | C; + var emptyObj: {}; + var c: C; + + // A type guard of the form typeof x === s, + // where s is a string literal with any value but 'string', 'number' or 'boolean', + // - when true, removes the primitive types string, number, and boolean from the type of x, or + // - when false, has no effect on the type of x. + + if (typeof strOrC === "Object") { + ~~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2365: Operator '===' cannot be applied to types '"string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function"' and '"Object"'. + c = strOrC; // C + } + else { + var r2: string = strOrC; // string + } + if (typeof numOrC === "Object") { + ~~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2365: Operator '===' cannot be applied to types '"string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function"' and '"Object"'. + c = numOrC; // C + } + else { + var r3: number = numOrC; // number + } + if (typeof boolOrC === "Object") { + ~~~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2365: Operator '===' cannot be applied to types '"string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function"' and '"Object"'. + c = boolOrC; // C + } + else { + var r4: boolean = boolOrC; // boolean + } + if (typeof strOrC === "Object" as string) { // comparison is OK with cast + c = strOrC; // error: but no narrowing to C + ~ +!!! error TS2322: Type 'string | C' is not assignable to type 'C'. +!!! error TS2322: Type 'string' is not assignable to type 'C'. + } + else { + var r5: string = strOrC; // error: no narrowing to string + ~~ +!!! error TS2322: Type 'string | C' is not assignable to type 'string'. +!!! error TS2322: Type 'C' is not assignable to type 'string'. + } + + if (typeof strOrNumOrBool === "Object") { + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2365: Operator '===' cannot be applied to types '"string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function"' and '"Object"'. + let q1: {} = strOrNumOrBool; // {} + } + else { + let q2: string | number | boolean = strOrNumOrBool; // string | number | boolean + } + + // A type guard of the form typeof x !== s, where s is a string literal, + // - when true, narrows the type of x by typeof x === s when false, or + // - when false, narrows the type of x by typeof x === s when true. + if (typeof strOrC !== "Object") { + ~~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2365: Operator '!==' cannot be applied to types '"string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function"' and '"Object"'. + var r2: string = strOrC; // string + } + else { + c = strOrC; // C + } + if (typeof numOrC !== "Object") { + ~~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2365: Operator '!==' cannot be applied to types '"string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function"' and '"Object"'. + var r3: number = numOrC; // number + } + else { + c = numOrC; // C + } + if (typeof boolOrC !== "Object") { + ~~~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2365: Operator '!==' cannot be applied to types '"string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function"' and '"Object"'. + var r4: boolean = boolOrC; // boolean + } + else { + c = boolOrC; // C + } + + if (typeof strOrNumOrBool !== "Object") { + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2365: Operator '!==' cannot be applied to types '"string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function"' and '"Object"'. + let q1: string | number | boolean = strOrNumOrBool; // string | number | boolean + } + else { + let q2: {} = strOrNumOrBool; // {} + } + \ No newline at end of file diff --git a/tests/baselines/reference/typeGuardOfFormTypeOfOther.js b/tests/baselines/reference/typeGuardOfFormTypeOfOther.js index ee0b6f66332..571edc7e5a2 100644 --- a/tests/baselines/reference/typeGuardOfFormTypeOfOther.js +++ b/tests/baselines/reference/typeGuardOfFormTypeOfOther.js @@ -37,6 +37,12 @@ if (typeof boolOrC === "Object") { else { var r4: boolean = boolOrC; // boolean } +if (typeof strOrC === "Object" as string) { // comparison is OK with cast + c = strOrC; // error: but no narrowing to C +} +else { + var r5: string = strOrC; // error: no narrowing to string +} if (typeof strOrNumOrBool === "Object") { let q1: {} = strOrNumOrBool; // {} @@ -116,6 +122,12 @@ if (typeof boolOrC === "Object") { else { var r4 = boolOrC; // boolean } +if (typeof strOrC === "Object") { + c = strOrC; // error: but no narrowing to C +} +else { + var r5 = strOrC; // error: no narrowing to string +} if (typeof strOrNumOrBool === "Object") { var q1 = strOrNumOrBool; // {} } diff --git a/tests/baselines/reference/typeGuardOfFormTypeOfOther.symbols b/tests/baselines/reference/typeGuardOfFormTypeOfOther.symbols deleted file mode 100644 index a8760feda45..00000000000 --- a/tests/baselines/reference/typeGuardOfFormTypeOfOther.symbols +++ /dev/null @@ -1,153 +0,0 @@ -=== tests/cases/conformance/expressions/typeGuards/typeGuardOfFormTypeOfOther.ts === -class C { private p: string }; ->C : Symbol(C, Decl(typeGuardOfFormTypeOfOther.ts, 0, 0)) ->p : Symbol(C.p, Decl(typeGuardOfFormTypeOfOther.ts, 0, 9)) - -var str: string; ->str : Symbol(str, Decl(typeGuardOfFormTypeOfOther.ts, 2, 3)) - -var bool: boolean; ->bool : Symbol(bool, Decl(typeGuardOfFormTypeOfOther.ts, 3, 3)) - -var num: number; ->num : Symbol(num, Decl(typeGuardOfFormTypeOfOther.ts, 4, 3)) - -var strOrNum: string | number; ->strOrNum : Symbol(strOrNum, Decl(typeGuardOfFormTypeOfOther.ts, 5, 3)) - -var strOrBool: string | boolean; ->strOrBool : Symbol(strOrBool, Decl(typeGuardOfFormTypeOfOther.ts, 6, 3)) - -var numOrBool: number | boolean ->numOrBool : Symbol(numOrBool, Decl(typeGuardOfFormTypeOfOther.ts, 7, 3)) - -var strOrNumOrBool: string | number | boolean; ->strOrNumOrBool : Symbol(strOrNumOrBool, Decl(typeGuardOfFormTypeOfOther.ts, 8, 3)) - -var strOrC: string | C; ->strOrC : Symbol(strOrC, Decl(typeGuardOfFormTypeOfOther.ts, 9, 3)) ->C : Symbol(C, Decl(typeGuardOfFormTypeOfOther.ts, 0, 0)) - -var numOrC: number | C; ->numOrC : Symbol(numOrC, Decl(typeGuardOfFormTypeOfOther.ts, 10, 3)) ->C : Symbol(C, Decl(typeGuardOfFormTypeOfOther.ts, 0, 0)) - -var boolOrC: boolean | C; ->boolOrC : Symbol(boolOrC, Decl(typeGuardOfFormTypeOfOther.ts, 11, 3)) ->C : Symbol(C, Decl(typeGuardOfFormTypeOfOther.ts, 0, 0)) - -var emptyObj: {}; ->emptyObj : Symbol(emptyObj, Decl(typeGuardOfFormTypeOfOther.ts, 12, 3)) - -var c: C; ->c : Symbol(c, Decl(typeGuardOfFormTypeOfOther.ts, 13, 3)) ->C : Symbol(C, Decl(typeGuardOfFormTypeOfOther.ts, 0, 0)) - -// A type guard of the form typeof x === s, -// where s is a string literal with any value but 'string', 'number' or 'boolean', -// - when true, removes the primitive types string, number, and boolean from the type of x, or -// - when false, has no effect on the type of x. - -if (typeof strOrC === "Object") { ->strOrC : Symbol(strOrC, Decl(typeGuardOfFormTypeOfOther.ts, 9, 3)) - - c = strOrC; // C ->c : Symbol(c, Decl(typeGuardOfFormTypeOfOther.ts, 13, 3)) ->strOrC : Symbol(strOrC, Decl(typeGuardOfFormTypeOfOther.ts, 9, 3)) -} -else { - var r2: string = strOrC; // string ->r2 : Symbol(r2, Decl(typeGuardOfFormTypeOfOther.ts, 24, 7), Decl(typeGuardOfFormTypeOfOther.ts, 50, 7)) ->strOrC : Symbol(strOrC, Decl(typeGuardOfFormTypeOfOther.ts, 9, 3)) -} -if (typeof numOrC === "Object") { ->numOrC : Symbol(numOrC, Decl(typeGuardOfFormTypeOfOther.ts, 10, 3)) - - c = numOrC; // C ->c : Symbol(c, Decl(typeGuardOfFormTypeOfOther.ts, 13, 3)) ->numOrC : Symbol(numOrC, Decl(typeGuardOfFormTypeOfOther.ts, 10, 3)) -} -else { - var r3: number = numOrC; // number ->r3 : Symbol(r3, Decl(typeGuardOfFormTypeOfOther.ts, 30, 7), Decl(typeGuardOfFormTypeOfOther.ts, 56, 7)) ->numOrC : Symbol(numOrC, Decl(typeGuardOfFormTypeOfOther.ts, 10, 3)) -} -if (typeof boolOrC === "Object") { ->boolOrC : Symbol(boolOrC, Decl(typeGuardOfFormTypeOfOther.ts, 11, 3)) - - c = boolOrC; // C ->c : Symbol(c, Decl(typeGuardOfFormTypeOfOther.ts, 13, 3)) ->boolOrC : Symbol(boolOrC, Decl(typeGuardOfFormTypeOfOther.ts, 11, 3)) -} -else { - var r4: boolean = boolOrC; // boolean ->r4 : Symbol(r4, Decl(typeGuardOfFormTypeOfOther.ts, 36, 7), Decl(typeGuardOfFormTypeOfOther.ts, 62, 7)) ->boolOrC : Symbol(boolOrC, Decl(typeGuardOfFormTypeOfOther.ts, 11, 3)) -} - -if (typeof strOrNumOrBool === "Object") { ->strOrNumOrBool : Symbol(strOrNumOrBool, Decl(typeGuardOfFormTypeOfOther.ts, 8, 3)) - - let q1: {} = strOrNumOrBool; // {} ->q1 : Symbol(q1, Decl(typeGuardOfFormTypeOfOther.ts, 40, 7)) ->strOrNumOrBool : Symbol(strOrNumOrBool, Decl(typeGuardOfFormTypeOfOther.ts, 8, 3)) -} -else { - let q2: string | number | boolean = strOrNumOrBool; // string | number | boolean ->q2 : Symbol(q2, Decl(typeGuardOfFormTypeOfOther.ts, 43, 7)) ->strOrNumOrBool : Symbol(strOrNumOrBool, Decl(typeGuardOfFormTypeOfOther.ts, 8, 3)) -} - -// A type guard of the form typeof x !== s, where s is a string literal, -// - when true, narrows the type of x by typeof x === s when false, or -// - when false, narrows the type of x by typeof x === s when true. -if (typeof strOrC !== "Object") { ->strOrC : Symbol(strOrC, Decl(typeGuardOfFormTypeOfOther.ts, 9, 3)) - - var r2: string = strOrC; // string ->r2 : Symbol(r2, Decl(typeGuardOfFormTypeOfOther.ts, 24, 7), Decl(typeGuardOfFormTypeOfOther.ts, 50, 7)) ->strOrC : Symbol(strOrC, Decl(typeGuardOfFormTypeOfOther.ts, 9, 3)) -} -else { - c = strOrC; // C ->c : Symbol(c, Decl(typeGuardOfFormTypeOfOther.ts, 13, 3)) ->strOrC : Symbol(strOrC, Decl(typeGuardOfFormTypeOfOther.ts, 9, 3)) -} -if (typeof numOrC !== "Object") { ->numOrC : Symbol(numOrC, Decl(typeGuardOfFormTypeOfOther.ts, 10, 3)) - - var r3: number = numOrC; // number ->r3 : Symbol(r3, Decl(typeGuardOfFormTypeOfOther.ts, 30, 7), Decl(typeGuardOfFormTypeOfOther.ts, 56, 7)) ->numOrC : Symbol(numOrC, Decl(typeGuardOfFormTypeOfOther.ts, 10, 3)) -} -else { - c = numOrC; // C ->c : Symbol(c, Decl(typeGuardOfFormTypeOfOther.ts, 13, 3)) ->numOrC : Symbol(numOrC, Decl(typeGuardOfFormTypeOfOther.ts, 10, 3)) -} -if (typeof boolOrC !== "Object") { ->boolOrC : Symbol(boolOrC, Decl(typeGuardOfFormTypeOfOther.ts, 11, 3)) - - var r4: boolean = boolOrC; // boolean ->r4 : Symbol(r4, Decl(typeGuardOfFormTypeOfOther.ts, 36, 7), Decl(typeGuardOfFormTypeOfOther.ts, 62, 7)) ->boolOrC : Symbol(boolOrC, Decl(typeGuardOfFormTypeOfOther.ts, 11, 3)) -} -else { - c = boolOrC; // C ->c : Symbol(c, Decl(typeGuardOfFormTypeOfOther.ts, 13, 3)) ->boolOrC : Symbol(boolOrC, Decl(typeGuardOfFormTypeOfOther.ts, 11, 3)) -} - -if (typeof strOrNumOrBool !== "Object") { ->strOrNumOrBool : Symbol(strOrNumOrBool, Decl(typeGuardOfFormTypeOfOther.ts, 8, 3)) - - let q1: string | number | boolean = strOrNumOrBool; // string | number | boolean ->q1 : Symbol(q1, Decl(typeGuardOfFormTypeOfOther.ts, 69, 7)) ->strOrNumOrBool : Symbol(strOrNumOrBool, Decl(typeGuardOfFormTypeOfOther.ts, 8, 3)) -} -else { - let q2: {} = strOrNumOrBool; // {} ->q2 : Symbol(q2, Decl(typeGuardOfFormTypeOfOther.ts, 72, 7)) ->strOrNumOrBool : Symbol(strOrNumOrBool, Decl(typeGuardOfFormTypeOfOther.ts, 8, 3)) -} - diff --git a/tests/baselines/reference/typeGuardOfFormTypeOfOther.types b/tests/baselines/reference/typeGuardOfFormTypeOfOther.types deleted file mode 100644 index b87f6a2a004..00000000000 --- a/tests/baselines/reference/typeGuardOfFormTypeOfOther.types +++ /dev/null @@ -1,183 +0,0 @@ -=== tests/cases/conformance/expressions/typeGuards/typeGuardOfFormTypeOfOther.ts === -class C { private p: string }; ->C : C ->p : string - -var str: string; ->str : string - -var bool: boolean; ->bool : boolean - -var num: number; ->num : number - -var strOrNum: string | number; ->strOrNum : string | number - -var strOrBool: string | boolean; ->strOrBool : string | boolean - -var numOrBool: number | boolean ->numOrBool : number | boolean - -var strOrNumOrBool: string | number | boolean; ->strOrNumOrBool : string | number | boolean - -var strOrC: string | C; ->strOrC : string | C ->C : C - -var numOrC: number | C; ->numOrC : number | C ->C : C - -var boolOrC: boolean | C; ->boolOrC : boolean | C ->C : C - -var emptyObj: {}; ->emptyObj : {} - -var c: C; ->c : C ->C : C - -// A type guard of the form typeof x === s, -// where s is a string literal with any value but 'string', 'number' or 'boolean', -// - when true, removes the primitive types string, number, and boolean from the type of x, or -// - when false, has no effect on the type of x. - -if (typeof strOrC === "Object") { ->typeof strOrC === "Object" : boolean ->typeof strOrC : string ->strOrC : string | C ->"Object" : "Object" - - c = strOrC; // C ->c = strOrC : C ->c : C ->strOrC : C -} -else { - var r2: string = strOrC; // string ->r2 : string ->strOrC : string -} -if (typeof numOrC === "Object") { ->typeof numOrC === "Object" : boolean ->typeof numOrC : string ->numOrC : number | C ->"Object" : "Object" - - c = numOrC; // C ->c = numOrC : C ->c : C ->numOrC : C -} -else { - var r3: number = numOrC; // number ->r3 : number ->numOrC : number -} -if (typeof boolOrC === "Object") { ->typeof boolOrC === "Object" : boolean ->typeof boolOrC : string ->boolOrC : boolean | C ->"Object" : "Object" - - c = boolOrC; // C ->c = boolOrC : C ->c : C ->boolOrC : C -} -else { - var r4: boolean = boolOrC; // boolean ->r4 : boolean ->boolOrC : boolean -} - -if (typeof strOrNumOrBool === "Object") { ->typeof strOrNumOrBool === "Object" : boolean ->typeof strOrNumOrBool : string ->strOrNumOrBool : string | number | boolean ->"Object" : "Object" - - let q1: {} = strOrNumOrBool; // {} ->q1 : {} ->strOrNumOrBool : never -} -else { - let q2: string | number | boolean = strOrNumOrBool; // string | number | boolean ->q2 : string | number | boolean ->strOrNumOrBool : string | number | boolean -} - -// A type guard of the form typeof x !== s, where s is a string literal, -// - when true, narrows the type of x by typeof x === s when false, or -// - when false, narrows the type of x by typeof x === s when true. -if (typeof strOrC !== "Object") { ->typeof strOrC !== "Object" : boolean ->typeof strOrC : string ->strOrC : string | C ->"Object" : "Object" - - var r2: string = strOrC; // string ->r2 : string ->strOrC : string -} -else { - c = strOrC; // C ->c = strOrC : C ->c : C ->strOrC : C -} -if (typeof numOrC !== "Object") { ->typeof numOrC !== "Object" : boolean ->typeof numOrC : string ->numOrC : number | C ->"Object" : "Object" - - var r3: number = numOrC; // number ->r3 : number ->numOrC : number -} -else { - c = numOrC; // C ->c = numOrC : C ->c : C ->numOrC : C -} -if (typeof boolOrC !== "Object") { ->typeof boolOrC !== "Object" : boolean ->typeof boolOrC : string ->boolOrC : boolean | C ->"Object" : "Object" - - var r4: boolean = boolOrC; // boolean ->r4 : boolean ->boolOrC : boolean -} -else { - c = boolOrC; // C ->c = boolOrC : C ->c : C ->boolOrC : C -} - -if (typeof strOrNumOrBool !== "Object") { ->typeof strOrNumOrBool !== "Object" : boolean ->typeof strOrNumOrBool : string ->strOrNumOrBool : string | number | boolean ->"Object" : "Object" - - let q1: string | number | boolean = strOrNumOrBool; // string | number | boolean ->q1 : string | number | boolean ->strOrNumOrBool : string | number | boolean -} -else { - let q2: {} = strOrNumOrBool; // {} ->q2 : {} ->strOrNumOrBool : never -} - diff --git a/tests/baselines/reference/typeGuardOfFormTypeOfPrimitiveSubtype.types b/tests/baselines/reference/typeGuardOfFormTypeOfPrimitiveSubtype.types index 6302ef58005..4787c07d758 100644 --- a/tests/baselines/reference/typeGuardOfFormTypeOfPrimitiveSubtype.types +++ b/tests/baselines/reference/typeGuardOfFormTypeOfPrimitiveSubtype.types @@ -8,7 +8,7 @@ let b: {toString(): string}; if (typeof a === "number") { >typeof a === "number" : boolean ->typeof a : string +>typeof a : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >a : {} >"number" : "number" @@ -18,7 +18,7 @@ if (typeof a === "number") { } if (typeof a === "string") { >typeof a === "string" : boolean ->typeof a : string +>typeof a : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >a : {} >"string" : "string" @@ -28,7 +28,7 @@ if (typeof a === "string") { } if (typeof a === "boolean") { >typeof a === "boolean" : boolean ->typeof a : string +>typeof a : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >a : {} >"boolean" : "boolean" @@ -39,7 +39,7 @@ if (typeof a === "boolean") { if (typeof b === "number") { >typeof b === "number" : boolean ->typeof b : string +>typeof b : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >b : { toString(): string; } >"number" : "number" @@ -49,7 +49,7 @@ if (typeof b === "number") { } if (typeof b === "string") { >typeof b === "string" : boolean ->typeof b : string +>typeof b : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >b : { toString(): string; } >"string" : "string" @@ -59,7 +59,7 @@ if (typeof b === "string") { } if (typeof b === "boolean") { >typeof b === "boolean" : boolean ->typeof b : string +>typeof b : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >b : { toString(): string; } >"boolean" : "boolean" diff --git a/tests/baselines/reference/typeGuardOfFormTypeOfString.types b/tests/baselines/reference/typeGuardOfFormTypeOfString.types index e9960ac3019..6b3e048212a 100644 --- a/tests/baselines/reference/typeGuardOfFormTypeOfString.types +++ b/tests/baselines/reference/typeGuardOfFormTypeOfString.types @@ -46,7 +46,7 @@ var c: C; // - when false, removes the primitive type from the type of x. if (typeof strOrNum === "string") { >typeof strOrNum === "string" : boolean ->typeof strOrNum : string +>typeof strOrNum : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >strOrNum : string | number >"string" : "string" @@ -63,7 +63,7 @@ else { } if (typeof strOrBool === "string") { >typeof strOrBool === "string" : boolean ->typeof strOrBool : string +>typeof strOrBool : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >strOrBool : string | boolean >"string" : "string" @@ -80,7 +80,7 @@ else { } if (typeof strOrNumOrBool === "string") { >typeof strOrNumOrBool === "string" : boolean ->typeof strOrNumOrBool : string +>typeof strOrNumOrBool : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >strOrNumOrBool : string | number | boolean >"string" : "string" @@ -97,7 +97,7 @@ else { } if (typeof strOrC === "string") { >typeof strOrC === "string" : boolean ->typeof strOrC : string +>typeof strOrC : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >strOrC : string | C >"string" : "string" @@ -115,7 +115,7 @@ else { if (typeof numOrBool === "string") { >typeof numOrBool === "string" : boolean ->typeof numOrBool : string +>typeof numOrBool : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >numOrBool : number | boolean >"string" : "string" @@ -134,7 +134,7 @@ else { // - when false, narrows the type of x by typeof x === s when true. if (typeof strOrNum !== "string") { >typeof strOrNum !== "string" : boolean ->typeof strOrNum : string +>typeof strOrNum : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >strOrNum : string | number >"string" : "string" @@ -151,7 +151,7 @@ else { } if (typeof strOrBool !== "string") { >typeof strOrBool !== "string" : boolean ->typeof strOrBool : string +>typeof strOrBool : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >strOrBool : string | boolean >"string" : "string" @@ -168,7 +168,7 @@ else { } if (typeof strOrNumOrBool !== "string") { >typeof strOrNumOrBool !== "string" : boolean ->typeof strOrNumOrBool : string +>typeof strOrNumOrBool : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >strOrNumOrBool : string | number | boolean >"string" : "string" @@ -185,7 +185,7 @@ else { } if (typeof strOrC !== "string") { >typeof strOrC !== "string" : boolean ->typeof strOrC : string +>typeof strOrC : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >strOrC : string | C >"string" : "string" @@ -203,7 +203,7 @@ else { if (typeof numOrBool !== "string") { >typeof numOrBool !== "string" : boolean ->typeof numOrBool : string +>typeof numOrBool : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >numOrBool : number | boolean >"string" : "string" diff --git a/tests/baselines/reference/typeGuardRedundancy.types b/tests/baselines/reference/typeGuardRedundancy.types index 80de5f54ace..2023defbb43 100644 --- a/tests/baselines/reference/typeGuardRedundancy.types +++ b/tests/baselines/reference/typeGuardRedundancy.types @@ -7,11 +7,11 @@ var r1 = typeof x === "string" && typeof x === "string" ? x.substr : x.toFixed; >typeof x === "string" && typeof x === "string" ? x.substr : x.toFixed : (from: number, length?: number) => string >typeof x === "string" && typeof x === "string" : boolean >typeof x === "string" : boolean ->typeof x : string +>typeof x : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >x : string | number >"string" : "string" >typeof x === "string" : boolean ->typeof x : string +>typeof x : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >x : string >"string" : "string" >x.substr : (from: number, length?: number) => string @@ -28,11 +28,11 @@ var r2 = !(typeof x === "string" && typeof x === "string") ? x.toFixed : x.subst >(typeof x === "string" && typeof x === "string") : boolean >typeof x === "string" && typeof x === "string" : boolean >typeof x === "string" : boolean ->typeof x : string +>typeof x : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >x : string | number >"string" : "string" >typeof x === "string" : boolean ->typeof x : string +>typeof x : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >x : string >"string" : "string" >x.toFixed : (fractionDigits?: number) => string @@ -47,11 +47,11 @@ var r3 = typeof x === "string" || typeof x === "string" ? x.substr : x.toFixed; >typeof x === "string" || typeof x === "string" ? x.substr : x.toFixed : (from: number, length?: number) => string >typeof x === "string" || typeof x === "string" : boolean >typeof x === "string" : boolean ->typeof x : string +>typeof x : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >x : string | number >"string" : "string" >typeof x === "string" : boolean ->typeof x : string +>typeof x : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >x : number >"string" : "string" >x.substr : (from: number, length?: number) => string @@ -68,11 +68,11 @@ var r4 = !(typeof x === "string" || typeof x === "string") ? x.toFixed : x.subst >(typeof x === "string" || typeof x === "string") : boolean >typeof x === "string" || typeof x === "string" : boolean >typeof x === "string" : boolean ->typeof x : string +>typeof x : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >x : string | number >"string" : "string" >typeof x === "string" : boolean ->typeof x : string +>typeof x : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >x : number >"string" : "string" >x.toFixed : (fractionDigits?: number) => string diff --git a/tests/baselines/reference/typeGuardTautologicalConsistiency.types b/tests/baselines/reference/typeGuardTautologicalConsistiency.types index 0a6524dd26f..136b09674d8 100644 --- a/tests/baselines/reference/typeGuardTautologicalConsistiency.types +++ b/tests/baselines/reference/typeGuardTautologicalConsistiency.types @@ -4,13 +4,13 @@ let stringOrNumber: string | number; if (typeof stringOrNumber === "number") { >typeof stringOrNumber === "number" : boolean ->typeof stringOrNumber : string +>typeof stringOrNumber : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >stringOrNumber : string | number >"number" : "number" if (typeof stringOrNumber !== "number") { >typeof stringOrNumber !== "number" : boolean ->typeof stringOrNumber : string +>typeof stringOrNumber : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >stringOrNumber : number >"number" : "number" @@ -22,11 +22,11 @@ if (typeof stringOrNumber === "number") { if (typeof stringOrNumber === "number" && typeof stringOrNumber !== "number") { >typeof stringOrNumber === "number" && typeof stringOrNumber !== "number" : boolean >typeof stringOrNumber === "number" : boolean ->typeof stringOrNumber : string +>typeof stringOrNumber : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >stringOrNumber : string | number >"number" : "number" >typeof stringOrNumber !== "number" : boolean ->typeof stringOrNumber : string +>typeof stringOrNumber : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >stringOrNumber : number >"number" : "number" diff --git a/tests/baselines/reference/typeGuardTypeOfUndefined.types b/tests/baselines/reference/typeGuardTypeOfUndefined.types index 520d045d9e0..a28dab04490 100644 --- a/tests/baselines/reference/typeGuardTypeOfUndefined.types +++ b/tests/baselines/reference/typeGuardTypeOfUndefined.types @@ -6,13 +6,13 @@ function test1(a: any) { if (typeof a !== "undefined") { >typeof a !== "undefined" : boolean ->typeof a : string +>typeof a : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >a : any >"undefined" : "undefined" if (typeof a === "boolean") { >typeof a === "boolean" : boolean ->typeof a : string +>typeof a : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >a : any >"boolean" : "boolean" @@ -36,13 +36,13 @@ function test2(a: any) { if (typeof a === "undefined") { >typeof a === "undefined" : boolean ->typeof a : string +>typeof a : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >a : any >"undefined" : "undefined" if (typeof a === "boolean") { >typeof a === "boolean" : boolean ->typeof a : string +>typeof a : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >a : undefined >"boolean" : "boolean" @@ -67,11 +67,11 @@ function test3(a: any) { if (typeof a === "undefined" || typeof a === "boolean") { >typeof a === "undefined" || typeof a === "boolean" : boolean >typeof a === "undefined" : boolean ->typeof a : string +>typeof a : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >a : any >"undefined" : "undefined" >typeof a === "boolean" : boolean ->typeof a : string +>typeof a : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >a : any >"boolean" : "boolean" @@ -91,11 +91,11 @@ function test4(a: any) { if (typeof a !== "undefined" && typeof a === "boolean") { >typeof a !== "undefined" && typeof a === "boolean" : boolean >typeof a !== "undefined" : boolean ->typeof a : string +>typeof a : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >a : any >"undefined" : "undefined" >typeof a === "boolean" : boolean ->typeof a : string +>typeof a : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >a : any >"boolean" : "boolean" @@ -114,13 +114,13 @@ function test5(a: boolean | void) { if (typeof a !== "undefined") { >typeof a !== "undefined" : boolean ->typeof a : string +>typeof a : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >a : boolean | void >"undefined" : "undefined" if (typeof a === "boolean") { >typeof a === "boolean" : boolean ->typeof a : string +>typeof a : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >a : boolean >"boolean" : "boolean" @@ -144,13 +144,13 @@ function test6(a: boolean | void) { if (typeof a === "undefined") { >typeof a === "undefined" : boolean ->typeof a : string +>typeof a : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >a : boolean | void >"undefined" : "undefined" if (typeof a === "boolean") { >typeof a === "boolean" : boolean ->typeof a : string +>typeof a : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >a : boolean | void >"boolean" : "boolean" @@ -175,11 +175,11 @@ function test7(a: boolean | void) { if (typeof a === "undefined" || typeof a === "boolean") { >typeof a === "undefined" || typeof a === "boolean" : boolean >typeof a === "undefined" : boolean ->typeof a : string +>typeof a : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >a : boolean | void >"undefined" : "undefined" >typeof a === "boolean" : boolean ->typeof a : string +>typeof a : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >a : boolean >"boolean" : "boolean" @@ -199,11 +199,11 @@ function test8(a: boolean | void) { if (typeof a !== "undefined" && typeof a === "boolean") { >typeof a !== "undefined" && typeof a === "boolean" : boolean >typeof a !== "undefined" : boolean ->typeof a : string +>typeof a : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >a : boolean | void >"undefined" : "undefined" >typeof a === "boolean" : boolean ->typeof a : string +>typeof a : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >a : boolean >"boolean" : "boolean" @@ -222,13 +222,13 @@ function test9(a: boolean | number) { if (typeof a !== "undefined") { >typeof a !== "undefined" : boolean ->typeof a : string +>typeof a : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >a : number | boolean >"undefined" : "undefined" if (typeof a === "boolean") { >typeof a === "boolean" : boolean ->typeof a : string +>typeof a : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >a : number | boolean >"boolean" : "boolean" @@ -252,13 +252,13 @@ function test10(a: boolean | number) { if (typeof a === "undefined") { >typeof a === "undefined" : boolean ->typeof a : string +>typeof a : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >a : number | boolean >"undefined" : "undefined" if (typeof a === "boolean") { >typeof a === "boolean" : boolean ->typeof a : string +>typeof a : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >a : number | boolean >"boolean" : "boolean" @@ -283,11 +283,11 @@ function test11(a: boolean | number) { if (typeof a === "undefined" || typeof a === "boolean") { >typeof a === "undefined" || typeof a === "boolean" : boolean >typeof a === "undefined" : boolean ->typeof a : string +>typeof a : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >a : number | boolean >"undefined" : "undefined" >typeof a === "boolean" : boolean ->typeof a : string +>typeof a : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >a : number | boolean >"boolean" : "boolean" @@ -307,11 +307,11 @@ function test12(a: boolean | number) { if (typeof a !== "undefined" && typeof a === "boolean") { >typeof a !== "undefined" && typeof a === "boolean" : boolean >typeof a !== "undefined" : boolean ->typeof a : string +>typeof a : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >a : number | boolean >"undefined" : "undefined" >typeof a === "boolean" : boolean ->typeof a : string +>typeof a : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >a : number | boolean >"boolean" : "boolean" @@ -330,13 +330,13 @@ function test13(a: boolean | number | void) { if (typeof a !== "undefined") { >typeof a !== "undefined" : boolean ->typeof a : string +>typeof a : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >a : number | boolean | void >"undefined" : "undefined" if (typeof a === "boolean") { >typeof a === "boolean" : boolean ->typeof a : string +>typeof a : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >a : number | boolean >"boolean" : "boolean" @@ -360,13 +360,13 @@ function test14(a: boolean | number | void) { if (typeof a === "undefined") { >typeof a === "undefined" : boolean ->typeof a : string +>typeof a : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >a : number | boolean | void >"undefined" : "undefined" if (typeof a === "boolean") { >typeof a === "boolean" : boolean ->typeof a : string +>typeof a : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >a : number | boolean | void >"boolean" : "boolean" @@ -391,11 +391,11 @@ function test15(a: boolean | number | void) { if (typeof a === "undefined" || typeof a === "boolean") { >typeof a === "undefined" || typeof a === "boolean" : boolean >typeof a === "undefined" : boolean ->typeof a : string +>typeof a : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >a : number | boolean | void >"undefined" : "undefined" >typeof a === "boolean" : boolean ->typeof a : string +>typeof a : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >a : number | boolean >"boolean" : "boolean" @@ -415,11 +415,11 @@ function test16(a: boolean | number | void) { if (typeof a !== "undefined" && typeof a === "boolean") { >typeof a !== "undefined" && typeof a === "boolean" : boolean >typeof a !== "undefined" : boolean ->typeof a : string +>typeof a : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >a : number | boolean | void >"undefined" : "undefined" >typeof a === "boolean" : boolean ->typeof a : string +>typeof a : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >a : number | boolean >"boolean" : "boolean" diff --git a/tests/baselines/reference/typeGuardsAsAssertions.types b/tests/baselines/reference/typeGuardsAsAssertions.types index bdda2eafefd..06dda2691be 100644 --- a/tests/baselines/reference/typeGuardsAsAssertions.types +++ b/tests/baselines/reference/typeGuardsAsAssertions.types @@ -118,7 +118,7 @@ function foo1() { >x : string | number | boolean >typeof x === "string" ? x.slice() : "abc" : string >typeof x === "string" : boolean ->typeof x : string +>typeof x : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >x : string | number >"string" : "string" >x.slice() : string @@ -152,7 +152,7 @@ function foo2() { if (typeof x === "string") { >typeof x === "string" : boolean ->typeof x : string +>typeof x : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >x : string | number >"string" : "string" @@ -211,7 +211,7 @@ function f2() { if (typeof x === "string") { >typeof x === "string" : boolean ->typeof x : string +>typeof x : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >x : undefined >"string" : "string" @@ -254,7 +254,7 @@ function f4() { if (typeof x === "boolean") { >typeof x === "boolean" : boolean ->typeof x : string +>typeof x : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >x : undefined >"boolean" : "boolean" @@ -272,11 +272,11 @@ function f5(x: string | number) { if (typeof x === "string" && typeof x === "number") { >typeof x === "string" && typeof x === "number" : boolean >typeof x === "string" : boolean ->typeof x : string +>typeof x : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >x : string | number >"string" : "string" >typeof x === "number" : boolean ->typeof x : string +>typeof x : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >x : string >"number" : "number" diff --git a/tests/baselines/reference/typeGuardsInClassAccessors.types b/tests/baselines/reference/typeGuardsInClassAccessors.types index 2250657e453..71e427124c4 100644 --- a/tests/baselines/reference/typeGuardsInClassAccessors.types +++ b/tests/baselines/reference/typeGuardsInClassAccessors.types @@ -26,7 +26,7 @@ class ClassWithAccessors { >num : number >typeof var1 === "string" && var1.length : number >typeof var1 === "string" : boolean ->typeof var1 : string +>typeof var1 : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >var1 : string | number >"string" : "string" >var1.length : number @@ -42,7 +42,7 @@ class ClassWithAccessors { >num : number >typeof var2 === "string" && var2.length : number >typeof var2 === "string" : boolean ->typeof var2 : string +>typeof var2 : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >var2 : string | number >"string" : "string" >var2.length : number @@ -63,7 +63,7 @@ class ClassWithAccessors { >num : number >typeof var1 === "string" && var1.length : number >typeof var1 === "string" : boolean ->typeof var1 : string +>typeof var1 : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >var1 : string | number >"string" : "string" >var1.length : number @@ -76,7 +76,7 @@ class ClassWithAccessors { >num : number >typeof param === "string" && param.length : number >typeof param === "string" : boolean ->typeof param : string +>typeof param : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >param : string | number >"string" : "string" >param.length : number @@ -92,7 +92,7 @@ class ClassWithAccessors { >num : number >typeof var2 === "string" && var2.length : number >typeof var2 === "string" : boolean ->typeof var2 : string +>typeof var2 : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >var2 : string | number >"string" : "string" >var2.length : number @@ -109,7 +109,7 @@ class ClassWithAccessors { >num : number >typeof var1 === "string" && var1.length : number >typeof var1 === "string" : boolean ->typeof var1 : string +>typeof var1 : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >var1 : string | number >"string" : "string" >var1.length : number @@ -125,7 +125,7 @@ class ClassWithAccessors { >num : number >typeof var2 === "string" && var2.length : number >typeof var2 === "string" : boolean ->typeof var2 : string +>typeof var2 : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >var2 : string | number >"string" : "string" >var2.length : number @@ -146,7 +146,7 @@ class ClassWithAccessors { >num : number >typeof var1 === "string" && var1.length : number >typeof var1 === "string" : boolean ->typeof var1 : string +>typeof var1 : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >var1 : string | number >"string" : "string" >var1.length : number @@ -159,7 +159,7 @@ class ClassWithAccessors { >num : number >typeof param === "string" && param.length : number >typeof param === "string" : boolean ->typeof param : string +>typeof param : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >param : string | number >"string" : "string" >param.length : number @@ -175,7 +175,7 @@ class ClassWithAccessors { >num : number >typeof var2 === "string" && var2.length : number >typeof var2 === "string" : boolean ->typeof var2 : string +>typeof var2 : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >var2 : string | number >"string" : "string" >var2.length : number @@ -192,7 +192,7 @@ class ClassWithAccessors { >num : number >typeof var1 === "string" && var1.length : number >typeof var1 === "string" : boolean ->typeof var1 : string +>typeof var1 : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >var1 : string | number >"string" : "string" >var1.length : number @@ -208,7 +208,7 @@ class ClassWithAccessors { >num : number >typeof var2 === "string" && var2.length : number >typeof var2 === "string" : boolean ->typeof var2 : string +>typeof var2 : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >var2 : string | number >"string" : "string" >var2.length : number @@ -229,7 +229,7 @@ class ClassWithAccessors { >num : number >typeof var1 === "string" && var1.length : number >typeof var1 === "string" : boolean ->typeof var1 : string +>typeof var1 : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >var1 : string | number >"string" : "string" >var1.length : number @@ -242,7 +242,7 @@ class ClassWithAccessors { >num : number >typeof param === "string" && param.length : number >typeof param === "string" : boolean ->typeof param : string +>typeof param : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >param : string | number >"string" : "string" >param.length : number @@ -258,7 +258,7 @@ class ClassWithAccessors { >num : number >typeof var2 === "string" && var2.length : number >typeof var2 === "string" : boolean ->typeof var2 : string +>typeof var2 : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >var2 : string | number >"string" : "string" >var2.length : number @@ -275,7 +275,7 @@ class ClassWithAccessors { >num : number >typeof var1 === "string" && var1.length : number >typeof var1 === "string" : boolean ->typeof var1 : string +>typeof var1 : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >var1 : string | number >"string" : "string" >var1.length : number @@ -291,7 +291,7 @@ class ClassWithAccessors { >num : number >typeof var2 === "string" && var2.length : number >typeof var2 === "string" : boolean ->typeof var2 : string +>typeof var2 : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >var2 : string | number >"string" : "string" >var2.length : number @@ -312,7 +312,7 @@ class ClassWithAccessors { >num : number >typeof var1 === "string" && var1.length : number >typeof var1 === "string" : boolean ->typeof var1 : string +>typeof var1 : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >var1 : string | number >"string" : "string" >var1.length : number @@ -325,7 +325,7 @@ class ClassWithAccessors { >num : number >typeof param === "string" && param.length : number >typeof param === "string" : boolean ->typeof param : string +>typeof param : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >param : string | number >"string" : "string" >param.length : number @@ -341,7 +341,7 @@ class ClassWithAccessors { >num : number >typeof var2 === "string" && var2.length : number >typeof var2 === "string" : boolean ->typeof var2 : string +>typeof var2 : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >var2 : string | number >"string" : "string" >var2.length : number diff --git a/tests/baselines/reference/typeGuardsInClassMethods.types b/tests/baselines/reference/typeGuardsInClassMethods.types index 600e3e36ab0..3a45abcf155 100644 --- a/tests/baselines/reference/typeGuardsInClassMethods.types +++ b/tests/baselines/reference/typeGuardsInClassMethods.types @@ -21,7 +21,7 @@ class C1 { >num : number >typeof var1 === "string" && var1.length : number >typeof var1 === "string" : boolean ->typeof var1 : string +>typeof var1 : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >var1 : string | number >"string" : "string" >var1.length : number @@ -37,7 +37,7 @@ class C1 { >num : number >typeof var2 === "string" && var2.length : number >typeof var2 === "string" : boolean ->typeof var2 : string +>typeof var2 : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >var2 : string | number >"string" : "string" >var2.length : number @@ -50,7 +50,7 @@ class C1 { >num : number >typeof param === "string" && param.length : number >typeof param === "string" : boolean ->typeof param : string +>typeof param : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >param : string | number >"string" : "string" >param.length : number @@ -68,7 +68,7 @@ class C1 { >num : number >typeof var1 === "string" && var1.length : number >typeof var1 === "string" : boolean ->typeof var1 : string +>typeof var1 : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >var1 : string | number >"string" : "string" >var1.length : number @@ -84,7 +84,7 @@ class C1 { >num : number >typeof var2 === "string" && var2.length : number >typeof var2 === "string" : boolean ->typeof var2 : string +>typeof var2 : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >var2 : string | number >"string" : "string" >var2.length : number @@ -97,7 +97,7 @@ class C1 { >num : number >typeof param === "string" && param.length : number >typeof param === "string" : boolean ->typeof param : string +>typeof param : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >param : string | number >"string" : "string" >param.length : number @@ -115,7 +115,7 @@ class C1 { >num : number >typeof var1 === "string" && var1.length : number >typeof var1 === "string" : boolean ->typeof var1 : string +>typeof var1 : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >var1 : string | number >"string" : "string" >var1.length : number @@ -131,7 +131,7 @@ class C1 { >num : number >typeof var2 === "string" && var2.length : number >typeof var2 === "string" : boolean ->typeof var2 : string +>typeof var2 : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >var2 : string | number >"string" : "string" >var2.length : number @@ -144,7 +144,7 @@ class C1 { >num : number >typeof param === "string" && param.length : number >typeof param === "string" : boolean ->typeof param : string +>typeof param : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >param : string | number >"string" : "string" >param.length : number @@ -162,7 +162,7 @@ class C1 { >num : number >typeof var1 === "string" && var1.length : number >typeof var1 === "string" : boolean ->typeof var1 : string +>typeof var1 : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >var1 : string | number >"string" : "string" >var1.length : number @@ -178,7 +178,7 @@ class C1 { >num : number >typeof var2 === "string" && var2.length : number >typeof var2 === "string" : boolean ->typeof var2 : string +>typeof var2 : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >var2 : string | number >"string" : "string" >var2.length : number @@ -191,7 +191,7 @@ class C1 { >num : number >typeof param === "string" && param.length : number >typeof param === "string" : boolean ->typeof param : string +>typeof param : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >param : string | number >"string" : "string" >param.length : number @@ -209,7 +209,7 @@ class C1 { >num : number >typeof var1 === "string" && var1.length : number >typeof var1 === "string" : boolean ->typeof var1 : string +>typeof var1 : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >var1 : string | number >"string" : "string" >var1.length : number @@ -225,7 +225,7 @@ class C1 { >num : number >typeof var2 === "string" && var2.length : number >typeof var2 === "string" : boolean ->typeof var2 : string +>typeof var2 : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >var2 : string | number >"string" : "string" >var2.length : number @@ -238,7 +238,7 @@ class C1 { >num : number >typeof param === "string" && param.length : number >typeof param === "string" : boolean ->typeof param : string +>typeof param : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >param : string | number >"string" : "string" >param.length : number diff --git a/tests/baselines/reference/typeGuardsInConditionalExpression.types b/tests/baselines/reference/typeGuardsInConditionalExpression.types index 165eecd3514..85d5380675d 100644 --- a/tests/baselines/reference/typeGuardsInConditionalExpression.types +++ b/tests/baselines/reference/typeGuardsInConditionalExpression.types @@ -13,7 +13,7 @@ function foo(x: number | string) { return typeof x === "string" >typeof x === "string" ? x.length // string : x++ : number >typeof x === "string" : boolean ->typeof x : string +>typeof x : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >x : string | number >"string" : "string" @@ -33,7 +33,7 @@ function foo2(x: number | string) { return typeof x === "string" >typeof x === "string" ? ((x = "hello") && x) // string : x : string | number >typeof x === "string" : boolean ->typeof x : string +>typeof x : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >x : string | number >"string" : "string" @@ -56,7 +56,7 @@ function foo3(x: number | string) { return typeof x === "string" >typeof x === "string" ? ((x = 10) && x) // number : x : number >typeof x === "string" : boolean ->typeof x : string +>typeof x : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >x : string | number >"string" : "string" @@ -79,7 +79,7 @@ function foo4(x: number | string) { return typeof x === "string" >typeof x === "string" ? x // string : ((x = 10) && x) : string | number >typeof x === "string" : boolean ->typeof x : string +>typeof x : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >x : string | number >"string" : "string" @@ -102,7 +102,7 @@ function foo5(x: number | string) { return typeof x === "string" >typeof x === "string" ? x // string : ((x = "hello") && x) : string >typeof x === "string" : boolean ->typeof x : string +>typeof x : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >x : string | number >"string" : "string" @@ -126,7 +126,7 @@ function foo6(x: number | string) { return typeof x === "string" >typeof x === "string" ? ((x = 10) && x) // number : ((x = "hello") && x) : string | number >typeof x === "string" : boolean ->typeof x : string +>typeof x : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >x : string | number >"string" : "string" @@ -155,7 +155,7 @@ function foo7(x: number | string | boolean) { return typeof x === "string" >typeof x === "string" ? x === "hello" // boolean : typeof x === "boolean" ? x // boolean : x == 10 : boolean >typeof x === "string" : boolean ->typeof x : string +>typeof x : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >x : string | number | boolean >"string" : "string" @@ -167,7 +167,7 @@ function foo7(x: number | string | boolean) { : typeof x === "boolean" >typeof x === "boolean" ? x // boolean : x == 10 : boolean >typeof x === "boolean" : boolean ->typeof x : string +>typeof x : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >x : number | boolean >"boolean" : "boolean" @@ -189,7 +189,7 @@ function foo8(x: number | string | boolean) { return typeof x === "string" >typeof x === "string" ? x === "hello" : ((b = x) && // number | boolean (typeof x === "boolean" ? x // boolean : x == 10)) : boolean >typeof x === "string" : boolean ->typeof x : string +>typeof x : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >x : string | number | boolean >"string" : "string" @@ -210,7 +210,7 @@ function foo8(x: number | string | boolean) { >(typeof x === "boolean" ? x // boolean : x == 10) : boolean >typeof x === "boolean" ? x // boolean : x == 10 : boolean >typeof x === "boolean" : boolean ->typeof x : string +>typeof x : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >x : number | boolean >"boolean" : "boolean" @@ -234,7 +234,7 @@ function foo9(x: number | string) { return typeof x === "string" >typeof x === "string" ? ((y = x.length) && x === "hello") // boolean : x === 10 : boolean >typeof x === "string" : boolean ->typeof x : string +>typeof x : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >x : string | number >"string" : "string" @@ -267,7 +267,7 @@ function foo10(x: number | string | boolean) { return typeof x === "string" >typeof x === "string" ? x // string : ((b = x) // x is number | boolean && typeof x === "number" && x.toString()) : string >typeof x === "string" : boolean ->typeof x : string +>typeof x : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >x : string | number | boolean >"string" : "string" @@ -285,7 +285,7 @@ function foo10(x: number | string | boolean) { && typeof x === "number" >typeof x === "number" : boolean ->typeof x : string +>typeof x : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >x : number | boolean >"number" : "number" @@ -306,7 +306,7 @@ function foo11(x: number | string | boolean) { return typeof x === "string" >typeof x === "string" ? x // string : ((b = x) // x is number | boolean && typeof x === "number" && (x = 10) // assignment to x && x) : string | number >typeof x === "string" : boolean ->typeof x : string +>typeof x : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >x : string | number | boolean >"string" : "string" @@ -325,7 +325,7 @@ function foo11(x: number | string | boolean) { && typeof x === "number" >typeof x === "number" : boolean ->typeof x : string +>typeof x : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >x : number | boolean >"number" : "number" @@ -349,7 +349,7 @@ function foo12(x: number | string | boolean) { return typeof x === "string" >typeof x === "string" ? ((x = 10) && x.toString().length) // number : ((b = x) // x is number | boolean && typeof x === "number" && x) : number >typeof x === "string" : boolean ->typeof x : string +>typeof x : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >x : string | number | boolean >"string" : "string" @@ -378,7 +378,7 @@ function foo12(x: number | string | boolean) { && typeof x === "number" >typeof x === "number" : boolean ->typeof x : string +>typeof x : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >x : number | boolean >"number" : "number" diff --git a/tests/baselines/reference/typeGuardsInDoStatement.types b/tests/baselines/reference/typeGuardsInDoStatement.types index fe14cff375f..c663ebbea54 100644 --- a/tests/baselines/reference/typeGuardsInDoStatement.types +++ b/tests/baselines/reference/typeGuardsInDoStatement.types @@ -22,7 +22,7 @@ function a(x: string | number | boolean) { } while (typeof x === "string") >typeof x === "string" : boolean ->typeof x : string +>typeof x : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >x : string | number | boolean >"string" : "string" @@ -52,7 +52,7 @@ function b(x: string | number | boolean) { } while (typeof x === "string") >typeof x === "string" : boolean ->typeof x : string +>typeof x : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >x : string | number | boolean >"string" : "string" @@ -82,7 +82,7 @@ function c(x: string | number) { } while (typeof x === "string") >typeof x === "string" : boolean ->typeof x : string +>typeof x : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >x : string | number >"string" : "string" diff --git a/tests/baselines/reference/typeGuardsInExternalModule.types b/tests/baselines/reference/typeGuardsInExternalModule.types index a0c33af4557..86b47f9b5c6 100644 --- a/tests/baselines/reference/typeGuardsInExternalModule.types +++ b/tests/baselines/reference/typeGuardsInExternalModule.types @@ -11,7 +11,7 @@ var var1: string | number; if (typeof var1 === "string") { >typeof var1 === "string" : boolean ->typeof var1 : string +>typeof var1 : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >var1 : string | number >"string" : "string" @@ -38,7 +38,7 @@ export var var2: string | number; if (typeof var2 === "string") { >typeof var2 === "string" : boolean ->typeof var2 : string +>typeof var2 : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >var2 : string | number >"string" : "string" diff --git a/tests/baselines/reference/typeGuardsInForStatement.types b/tests/baselines/reference/typeGuardsInForStatement.types index 1d600d52d13..4ad1a283d40 100644 --- a/tests/baselines/reference/typeGuardsInForStatement.types +++ b/tests/baselines/reference/typeGuardsInForStatement.types @@ -11,7 +11,7 @@ function a(x: string | number) { >x : string | number >undefined : undefined >typeof x !== "number" : boolean ->typeof x : string +>typeof x : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >x : string | number >"number" : "number" >x = undefined : undefined @@ -33,7 +33,7 @@ function b(x: string | number) { >x : string | number >undefined : undefined >typeof x !== "number" : boolean ->typeof x : string +>typeof x : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >x : string | number >"number" : "number" >x = undefined : undefined @@ -58,7 +58,7 @@ function c(x: string | number) { >x : string | number >undefined : undefined >typeof x !== "number" : boolean ->typeof x : string +>typeof x : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >x : string | number >"number" : "number" >x = undefined : undefined diff --git a/tests/baselines/reference/typeGuardsInFunction.types b/tests/baselines/reference/typeGuardsInFunction.types index 6a007dd7c95..a7dca0f709b 100644 --- a/tests/baselines/reference/typeGuardsInFunction.types +++ b/tests/baselines/reference/typeGuardsInFunction.types @@ -20,7 +20,7 @@ function f(param: string | number) { >num : number >typeof var1 === "string" && var1.length : number >typeof var1 === "string" : boolean ->typeof var1 : string +>typeof var1 : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >var1 : string | number >"string" : "string" >var1.length : number @@ -36,7 +36,7 @@ function f(param: string | number) { >num : number >typeof var2 === "string" && var2.length : number >typeof var2 === "string" : boolean ->typeof var2 : string +>typeof var2 : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >var2 : string | number >"string" : "string" >var2.length : number @@ -49,7 +49,7 @@ function f(param: string | number) { >num : number >typeof param === "string" && param.length : number >typeof param === "string" : boolean ->typeof param : string +>typeof param : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >param : string | number >"string" : "string" >param.length : number @@ -74,7 +74,7 @@ function f1(param: string | number) { >num : number >typeof var1 === "string" && var1.length : number >typeof var1 === "string" : boolean ->typeof var1 : string +>typeof var1 : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >var1 : string | number >"string" : "string" >var1.length : number @@ -87,7 +87,7 @@ function f1(param: string | number) { >num : number >typeof var2 === "string" && var2.length : number >typeof var2 === "string" : boolean ->typeof var2 : string +>typeof var2 : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >var2 : string | number >"string" : "string" >var2.length : number @@ -100,7 +100,7 @@ function f1(param: string | number) { >num : number >typeof param === "string" && param.length : number >typeof param === "string" : boolean ->typeof param : string +>typeof param : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >param : string | number >"string" : "string" >param.length : number @@ -116,7 +116,7 @@ function f1(param: string | number) { >num : number >typeof var3 === "string" && var3.length : number >typeof var3 === "string" : boolean ->typeof var3 : string +>typeof var3 : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >var3 : string | number >"string" : "string" >var3.length : number @@ -128,7 +128,7 @@ function f1(param: string | number) { >num : number >typeof param1 === "string" && param1.length : number >typeof param1 === "string" : boolean ->typeof param1 : string +>typeof param1 : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >param1 : string | number >"string" : "string" >param1.length : number @@ -158,7 +158,7 @@ function f2(param: string | number) { >num : number >typeof var1 === "string" && var1.length : number >typeof var1 === "string" : boolean ->typeof var1 : string +>typeof var1 : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >var1 : string | number >"string" : "string" >var1.length : number @@ -171,7 +171,7 @@ function f2(param: string | number) { >num : number >typeof var2 === "string" && var2.length : number >typeof var2 === "string" : boolean ->typeof var2 : string +>typeof var2 : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >var2 : string | number >"string" : "string" >var2.length : number @@ -184,7 +184,7 @@ function f2(param: string | number) { >num : number >typeof param === "string" && param.length : number >typeof param === "string" : boolean ->typeof param : string +>typeof param : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >param : string | number >"string" : "string" >param.length : number @@ -200,7 +200,7 @@ function f2(param: string | number) { >num : number >typeof var3 === "string" && var3.length : number >typeof var3 === "string" : boolean ->typeof var3 : string +>typeof var3 : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >var3 : string | number >"string" : "string" >var3.length : number @@ -212,7 +212,7 @@ function f2(param: string | number) { >num : number >typeof param1 === "string" && param1.length : number >typeof param1 === "string" : boolean ->typeof param1 : string +>typeof param1 : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >param1 : string | number >"string" : "string" >param1.length : number @@ -245,7 +245,7 @@ function f3(param: string | number) { >num : number >typeof var1 === "string" && var1.length : number >typeof var1 === "string" : boolean ->typeof var1 : string +>typeof var1 : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >var1 : string | number >"string" : "string" >var1.length : number @@ -258,7 +258,7 @@ function f3(param: string | number) { >num : number >typeof var2 === "string" && var2.length : number >typeof var2 === "string" : boolean ->typeof var2 : string +>typeof var2 : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >var2 : string | number >"string" : "string" >var2.length : number @@ -271,7 +271,7 @@ function f3(param: string | number) { >num : number >typeof param === "string" && param.length : number >typeof param === "string" : boolean ->typeof param : string +>typeof param : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >param : string | number >"string" : "string" >param.length : number @@ -287,7 +287,7 @@ function f3(param: string | number) { >num : number >typeof var3 === "string" && var3.length : number >typeof var3 === "string" : boolean ->typeof var3 : string +>typeof var3 : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >var3 : string | number >"string" : "string" >var3.length : number @@ -299,7 +299,7 @@ function f3(param: string | number) { >num : number >typeof param1 === "string" && param1.length : number >typeof param1 === "string" : boolean ->typeof param1 : string +>typeof param1 : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >param1 : string | number >"string" : "string" >param1.length : number @@ -329,7 +329,7 @@ strOrNum = typeof f4() === "string" && f4(); // string | number >strOrNum : string | number >typeof f4() === "string" && f4() : string | number >typeof f4() === "string" : boolean ->typeof f4() : string +>typeof f4() : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >f4() : string | number >f4 : () => string | number >"string" : "string" diff --git a/tests/baselines/reference/typeGuardsInFunctionAndModuleBlock.types b/tests/baselines/reference/typeGuardsInFunctionAndModuleBlock.types index 0cb312ffb1a..a425e4d632e 100644 --- a/tests/baselines/reference/typeGuardsInFunctionAndModuleBlock.types +++ b/tests/baselines/reference/typeGuardsInFunctionAndModuleBlock.types @@ -8,7 +8,7 @@ function foo(x: number | string | boolean) { return typeof x === "string" >typeof x === "string" ? x : function f() { var b = x; // number | boolean return typeof x === "boolean" ? x.toString() // boolean : x.toString(); // number } () : string >typeof x === "string" : boolean ->typeof x : string +>typeof x : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >x : string | number | boolean >"string" : "string" @@ -27,7 +27,7 @@ function foo(x: number | string | boolean) { return typeof x === "boolean" >typeof x === "boolean" ? x.toString() // boolean : x.toString() : string >typeof x === "boolean" : boolean ->typeof x : string +>typeof x : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >x : number | boolean >"boolean" : "boolean" @@ -52,7 +52,7 @@ function foo2(x: number | string | boolean) { return typeof x === "string" >typeof x === "string" ? x : function f(a: number | boolean) { var b = x; // new scope - number | boolean return typeof x === "boolean" ? x.toString() // boolean : x.toString(); // number } (x) : string >typeof x === "string" : boolean ->typeof x : string +>typeof x : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >x : string | number | boolean >"string" : "string" @@ -72,7 +72,7 @@ function foo2(x: number | string | boolean) { return typeof x === "boolean" >typeof x === "boolean" ? x.toString() // boolean : x.toString() : string >typeof x === "boolean" : boolean ->typeof x : string +>typeof x : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >x : number | boolean >"boolean" : "boolean" @@ -98,7 +98,7 @@ function foo3(x: number | string | boolean) { return typeof x === "string" >typeof x === "string" ? x : (() => { var b = x; // new scope - number | boolean return typeof x === "boolean" ? x.toString() // boolean : x.toString(); // number })() : string >typeof x === "string" : boolean ->typeof x : string +>typeof x : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >x : string | number | boolean >"string" : "string" @@ -117,7 +117,7 @@ function foo3(x: number | string | boolean) { return typeof x === "boolean" >typeof x === "boolean" ? x.toString() // boolean : x.toString() : string >typeof x === "boolean" : boolean ->typeof x : string +>typeof x : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >x : number | boolean >"boolean" : "boolean" @@ -142,7 +142,7 @@ function foo4(x: number | string | boolean) { return typeof x === "string" >typeof x === "string" ? x : ((a: number | boolean) => { var b = x; // new scope - number | boolean return typeof x === "boolean" ? x.toString() // boolean : x.toString(); // number })(x) : string >typeof x === "string" : boolean ->typeof x : string +>typeof x : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >x : string | number | boolean >"string" : "string" @@ -162,7 +162,7 @@ function foo4(x: number | string | boolean) { return typeof x === "boolean" >typeof x === "boolean" ? x.toString() // boolean : x.toString() : string >typeof x === "boolean" : boolean ->typeof x : string +>typeof x : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >x : number | boolean >"boolean" : "boolean" @@ -188,7 +188,7 @@ function foo5(x: number | string | boolean) { if (typeof x === "string") { >typeof x === "string" : boolean ->typeof x : string +>typeof x : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >x : string | number | boolean >"string" : "string" @@ -223,7 +223,7 @@ module m { if (typeof x === "string") { >typeof x === "string" : boolean ->typeof x : string +>typeof x : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >x : string | number | boolean >"string" : "string" @@ -238,7 +238,7 @@ module m { >y : string >typeof x === "boolean" ? x.toString() // boolean : x.toString() : string >typeof x === "boolean" : boolean ->typeof x : string +>typeof x : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >x : number | boolean >"boolean" : "boolean" @@ -275,7 +275,7 @@ module m1 { if (typeof x === "string") { >typeof x === "string" : boolean ->typeof x : string +>typeof x : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >x : string | number | boolean >"string" : "string" @@ -290,7 +290,7 @@ module m1 { >y : string >typeof x === "boolean" ? x.toString() // boolean : x.toString() : string >typeof x === "boolean" : boolean ->typeof x : string +>typeof x : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >x : number | boolean >"boolean" : "boolean" diff --git a/tests/baselines/reference/typeGuardsInGlobal.types b/tests/baselines/reference/typeGuardsInGlobal.types index 7935c05411e..7ccc2defe27 100644 --- a/tests/baselines/reference/typeGuardsInGlobal.types +++ b/tests/baselines/reference/typeGuardsInGlobal.types @@ -11,7 +11,7 @@ var var1: string | number; if (typeof var1 === "string") { >typeof var1 === "string" : boolean ->typeof var1 : string +>typeof var1 : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >var1 : string | number >"string" : "string" diff --git a/tests/baselines/reference/typeGuardsInModule.types b/tests/baselines/reference/typeGuardsInModule.types index f1efc45a248..a14c47e3cca 100644 --- a/tests/baselines/reference/typeGuardsInModule.types +++ b/tests/baselines/reference/typeGuardsInModule.types @@ -22,7 +22,7 @@ module m1 { >num : number >typeof var1 === "string" && var1.length : number >typeof var1 === "string" : boolean ->typeof var1 : string +>typeof var1 : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >var1 : string | number >"string" : "string" >var1.length : number @@ -35,7 +35,7 @@ module m1 { if (typeof var2 === "string") { >typeof var2 === "string" : boolean ->typeof var2 : string +>typeof var2 : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >var2 : string | number >"string" : "string" @@ -59,7 +59,7 @@ module m1 { if (typeof var3 === "string") { >typeof var3 === "string" : boolean ->typeof var3 : string +>typeof var3 : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >var3 : string | number >"string" : "string" @@ -94,7 +94,7 @@ module m2 { >num : number >typeof var1 === "string" && var1.length : number >typeof var1 === "string" : boolean ->typeof var1 : string +>typeof var1 : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >var1 : string | number >"string" : "string" >var1.length : number @@ -107,7 +107,7 @@ module m2 { >num : number >typeof var2 === "string" && var2.length : number >typeof var2 === "string" : boolean ->typeof var2 : string +>typeof var2 : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >var2 : string | number >"string" : "string" >var2.length : number @@ -120,7 +120,7 @@ module m2 { >strOrNum : string | number >typeof var3 === "string" && var3 : string >typeof var3 === "string" : boolean ->typeof var3 : string +>typeof var3 : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >var3 : string | number >"string" : "string" >var3 : string @@ -131,7 +131,7 @@ module m2 { if (typeof var4 === "string") { >typeof var4 === "string" : boolean ->typeof var4 : string +>typeof var4 : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >var4 : string | number >"string" : "string" @@ -155,7 +155,7 @@ module m2 { if (typeof var5 === "string") { >typeof var5 === "string" : boolean ->typeof var5 : string +>typeof var5 : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >var5 : string | number >"string" : "string" @@ -183,7 +183,7 @@ module m3.m4 { >num : number >typeof var1 === "string" && var1.length : number >typeof var1 === "string" : boolean ->typeof var1 : string +>typeof var1 : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >var1 : string | number >"string" : "string" >var1.length : number @@ -196,7 +196,7 @@ module m3.m4 { if (typeof var2 === "string") { >typeof var2 === "string" : boolean ->typeof var2 : string +>typeof var2 : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >var2 : string | number >"string" : "string" @@ -220,7 +220,7 @@ module m3.m4 { if (typeof var3 === "string") { >typeof var3 === "string" : boolean ->typeof var3 : string +>typeof var3 : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >var3 : string | number >"string" : "string" diff --git a/tests/baselines/reference/typeGuardsInProperties.types b/tests/baselines/reference/typeGuardsInProperties.types index 1f8151dff71..d40de30bd97 100644 --- a/tests/baselines/reference/typeGuardsInProperties.types +++ b/tests/baselines/reference/typeGuardsInProperties.types @@ -33,7 +33,7 @@ class C1 { >strOrNum : string | number >typeof this.pp1 === "string" && this.pp1 : string >typeof this.pp1 === "string" : boolean ->typeof this.pp1 : string +>typeof this.pp1 : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >this.pp1 : string | number >this : this >pp1 : string | number @@ -47,7 +47,7 @@ class C1 { >strOrNum : string | number >typeof this.pp2 === "string" && this.pp2 : string >typeof this.pp2 === "string" : boolean ->typeof this.pp2 : string +>typeof this.pp2 : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >this.pp2 : string | number >this : this >pp2 : string | number @@ -61,7 +61,7 @@ class C1 { >strOrNum : string | number >typeof this.pp3 === "string" && this.pp3 : string >typeof this.pp3 === "string" : boolean ->typeof this.pp3 : string +>typeof this.pp3 : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >this.pp3 : string | number >this : this >pp3 : string | number @@ -80,7 +80,7 @@ strOrNum = typeof c1.pp2 === "string" && c1.pp2; // string | number >strOrNum : string | number >typeof c1.pp2 === "string" && c1.pp2 : string >typeof c1.pp2 === "string" : boolean ->typeof c1.pp2 : string +>typeof c1.pp2 : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >c1.pp2 : string | number >c1 : C1 >pp2 : string | number @@ -94,7 +94,7 @@ strOrNum = typeof c1.pp3 === "string" && c1.pp3; // string | number >strOrNum : string | number >typeof c1.pp3 === "string" && c1.pp3 : string >typeof c1.pp3 === "string" : boolean ->typeof c1.pp3 : string +>typeof c1.pp3 : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >c1.pp3 : string | number >c1 : C1 >pp3 : string | number @@ -115,7 +115,7 @@ strOrNum = typeof obj1.x === "string" && obj1.x; // string | number >strOrNum : string | number >typeof obj1.x === "string" && obj1.x : string >typeof obj1.x === "string" : boolean ->typeof obj1.x : string +>typeof obj1.x : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >obj1.x : string | number >obj1 : { x: string | number; } >x : string | number diff --git a/tests/baselines/reference/typeGuardsInRightOperandOfAndAndOperator.types b/tests/baselines/reference/typeGuardsInRightOperandOfAndAndOperator.types index 54c1d0270b5..7235a1d80c2 100644 --- a/tests/baselines/reference/typeGuardsInRightOperandOfAndAndOperator.types +++ b/tests/baselines/reference/typeGuardsInRightOperandOfAndAndOperator.types @@ -8,7 +8,7 @@ function foo(x: number | string) { return typeof x === "string" && x.length === 10; // string >typeof x === "string" && x.length === 10 : boolean >typeof x === "string" : boolean ->typeof x : string +>typeof x : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >x : string | number >"string" : "string" >x.length === 10 : boolean @@ -25,7 +25,7 @@ function foo2(x: number | string) { return typeof x === "string" && ((x = 10) && x); // string | number >typeof x === "string" && ((x = 10) && x) : number >typeof x === "string" : boolean ->typeof x : string +>typeof x : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >x : string | number >"string" : "string" >((x = 10) && x) : number @@ -44,7 +44,7 @@ function foo3(x: number | string) { return typeof x === "string" && ((x = "hello") && x); // string | number >typeof x === "string" && ((x = "hello") && x) : string >typeof x === "string" : boolean ->typeof x : string +>typeof x : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >x : string | number >"string" : "string" >((x = "hello") && x) : string @@ -63,13 +63,13 @@ function foo4(x: number | string | boolean) { >typeof x !== "string" // string | number | boolean && typeof x !== "number" // number | boolean && x : boolean >typeof x !== "string" // string | number | boolean && typeof x !== "number" : boolean >typeof x !== "string" : boolean ->typeof x : string +>typeof x : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >x : string | number | boolean >"string" : "string" && typeof x !== "number" // number | boolean >typeof x !== "number" : boolean ->typeof x : string +>typeof x : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >x : number | boolean >"number" : "number" @@ -87,7 +87,7 @@ function foo5(x: number | string | boolean) { return typeof x !== "string" // string | number | boolean >typeof x !== "string" // string | number | boolean && ((b = x) && (typeof x !== "number" // number | boolean && x)) : boolean >typeof x !== "string" : boolean ->typeof x : string +>typeof x : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >x : string | number | boolean >"string" : "string" @@ -101,7 +101,7 @@ function foo5(x: number | string | boolean) { >(typeof x !== "number" // number | boolean && x) : boolean >typeof x !== "number" // number | boolean && x : boolean >typeof x !== "number" : boolean ->typeof x : string +>typeof x : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >x : number | boolean >"number" : "number" @@ -116,7 +116,7 @@ function foo6(x: number | string | boolean) { return typeof x !== "string" // string | number | boolean >typeof x !== "string" // string | number | boolean && (typeof x !== "number" // number | boolean ? x // boolean : x === 10) : boolean >typeof x !== "string" : boolean ->typeof x : string +>typeof x : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >x : string | number | boolean >"string" : "string" @@ -124,7 +124,7 @@ function foo6(x: number | string | boolean) { >(typeof x !== "number" // number | boolean ? x // boolean : x === 10) : boolean >typeof x !== "number" // number | boolean ? x // boolean : x === 10 : boolean >typeof x !== "number" : boolean ->typeof x : string +>typeof x : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >x : number | boolean >"number" : "number" @@ -150,7 +150,7 @@ function foo7(x: number | string | boolean) { return typeof x !== "string" >typeof x !== "string" && ((z = x) // number | boolean && (typeof x === "number" // change value of x ? ((x = 10) && x.toString()) // x is number // do not change value : ((y = x) && x.toString()))) : string >typeof x !== "string" : boolean ->typeof x : string +>typeof x : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >x : string | number | boolean >"string" : "string" @@ -166,7 +166,7 @@ function foo7(x: number | string | boolean) { >(typeof x === "number" // change value of x ? ((x = 10) && x.toString()) // x is number // do not change value : ((y = x) && x.toString())) : string >typeof x === "number" // change value of x ? ((x = 10) && x.toString()) // x is number // do not change value : ((y = x) && x.toString()) : string >typeof x === "number" : boolean ->typeof x : string +>typeof x : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >x : number | boolean >"number" : "number" diff --git a/tests/baselines/reference/typeGuardsInRightOperandOfOrOrOperator.types b/tests/baselines/reference/typeGuardsInRightOperandOfOrOrOperator.types index e8548ab1ef6..d8d807bad70 100644 --- a/tests/baselines/reference/typeGuardsInRightOperandOfOrOrOperator.types +++ b/tests/baselines/reference/typeGuardsInRightOperandOfOrOrOperator.types @@ -9,7 +9,7 @@ function foo(x: number | string) { return typeof x !== "string" || x.length === 10; // string >typeof x !== "string" || x.length === 10 : boolean >typeof x !== "string" : boolean ->typeof x : string +>typeof x : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >x : string | number >"string" : "string" >x.length === 10 : boolean @@ -26,7 +26,7 @@ function foo2(x: number | string) { return typeof x !== "string" || ((x = 10) || x); // string | number >typeof x !== "string" || ((x = 10) || x) : number | true >typeof x !== "string" : boolean ->typeof x : string +>typeof x : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >x : string | number >"string" : "string" >((x = 10) || x) : number @@ -45,7 +45,7 @@ function foo3(x: number | string) { return typeof x !== "string" || ((x = "hello") || x); // string | number >typeof x !== "string" || ((x = "hello") || x) : string | true >typeof x !== "string" : boolean ->typeof x : string +>typeof x : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >x : string | number >"string" : "string" >((x = "hello") || x) : string @@ -64,13 +64,13 @@ function foo4(x: number | string | boolean) { >typeof x === "string" // string | number | boolean || typeof x === "number" // number | boolean || x : boolean >typeof x === "string" // string | number | boolean || typeof x === "number" : boolean >typeof x === "string" : boolean ->typeof x : string +>typeof x : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >x : string | number | boolean >"string" : "string" || typeof x === "number" // number | boolean >typeof x === "number" : boolean ->typeof x : string +>typeof x : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >x : number | boolean >"number" : "number" @@ -88,7 +88,7 @@ function foo5(x: number | string | boolean) { return typeof x === "string" // string | number | boolean >typeof x === "string" // string | number | boolean || ((b = x) || (typeof x === "number" // number | boolean || x)) : number | boolean >typeof x === "string" : boolean ->typeof x : string +>typeof x : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >x : string | number | boolean >"string" : "string" @@ -102,7 +102,7 @@ function foo5(x: number | string | boolean) { >(typeof x === "number" // number | boolean || x) : boolean >typeof x === "number" // number | boolean || x : boolean >typeof x === "number" : boolean ->typeof x : string +>typeof x : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >x : number | boolean >"number" : "number" @@ -117,7 +117,7 @@ function foo6(x: number | string | boolean) { return typeof x === "string" // string | number | boolean >typeof x === "string" // string | number | boolean || (typeof x !== "number" // number | boolean ? x // boolean : x === 10) : boolean >typeof x === "string" : boolean ->typeof x : string +>typeof x : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >x : string | number | boolean >"string" : "string" @@ -125,7 +125,7 @@ function foo6(x: number | string | boolean) { >(typeof x !== "number" // number | boolean ? x // boolean : x === 10) : boolean >typeof x !== "number" // number | boolean ? x // boolean : x === 10 : boolean >typeof x !== "number" : boolean ->typeof x : string +>typeof x : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >x : number | boolean >"number" : "number" @@ -151,7 +151,7 @@ function foo7(x: number | string | boolean) { return typeof x === "string" >typeof x === "string" || ((z = x) // number | boolean || (typeof x === "number" // change value of x ? ((x = 10) && x.toString()) // number | boolean | string // do not change value : ((y = x) && x.toString()))) : string | number | true >typeof x === "string" : boolean ->typeof x : string +>typeof x : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >x : string | number | boolean >"string" : "string" @@ -167,7 +167,7 @@ function foo7(x: number | string | boolean) { >(typeof x === "number" // change value of x ? ((x = 10) && x.toString()) // number | boolean | string // do not change value : ((y = x) && x.toString())) : string >typeof x === "number" // change value of x ? ((x = 10) && x.toString()) // number | boolean | string // do not change value : ((y = x) && x.toString()) : string >typeof x === "number" : boolean ->typeof x : string +>typeof x : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >x : number | boolean >"number" : "number" diff --git a/tests/baselines/reference/typeGuardsInWhileStatement.types b/tests/baselines/reference/typeGuardsInWhileStatement.types index b0ea7959ec5..cdcff209c08 100644 --- a/tests/baselines/reference/typeGuardsInWhileStatement.types +++ b/tests/baselines/reference/typeGuardsInWhileStatement.types @@ -8,7 +8,7 @@ function a(x: string | number) { while (typeof x === "string") { >typeof x === "string" : boolean ->typeof x : string +>typeof x : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >x : string | number >"string" : "string" @@ -29,7 +29,7 @@ function b(x: string | number) { while (typeof x === "string") { >typeof x === "string" : boolean ->typeof x : string +>typeof x : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >x : string | number >"string" : "string" @@ -53,7 +53,7 @@ function c(x: string | number) { while (typeof x === "string") { >typeof x === "string" : boolean ->typeof x : string +>typeof x : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >x : string | number >"string" : "string" diff --git a/tests/baselines/reference/typeGuardsNestedAssignments.types b/tests/baselines/reference/typeGuardsNestedAssignments.types index 32ac85e270b..ba26f6c07aa 100644 --- a/tests/baselines/reference/typeGuardsNestedAssignments.types +++ b/tests/baselines/reference/typeGuardsNestedAssignments.types @@ -103,7 +103,7 @@ function f4() { if (typeof (x = getStringOrNumberOrNull()) === "number") { >typeof (x = getStringOrNumberOrNull()) === "number" : boolean ->typeof (x = getStringOrNumberOrNull()) : string +>typeof (x = getStringOrNumberOrNull()) : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >(x = getStringOrNumberOrNull()) : string | number | null >x = getStringOrNumberOrNull() : string | number | null >x : string | number | null diff --git a/tests/baselines/reference/typeGuardsObjectMethods.types b/tests/baselines/reference/typeGuardsObjectMethods.types index 5a795c336e2..4f3e888d76e 100644 --- a/tests/baselines/reference/typeGuardsObjectMethods.types +++ b/tests/baselines/reference/typeGuardsObjectMethods.types @@ -28,7 +28,7 @@ var obj1 = { >num : number >typeof var1 === "string" && var1.length : number >typeof var1 === "string" : boolean ->typeof var1 : string +>typeof var1 : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >var1 : string | number >"string" : "string" >var1.length : number @@ -44,7 +44,7 @@ var obj1 = { >num : number >typeof var2 === "string" && var2.length : number >typeof var2 === "string" : boolean ->typeof var2 : string +>typeof var2 : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >var2 : string | number >"string" : "string" >var2.length : number @@ -57,7 +57,7 @@ var obj1 = { >num : number >typeof param === "string" && param.length : number >typeof param === "string" : boolean ->typeof param : string +>typeof param : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >param : string | number >"string" : "string" >param.length : number @@ -77,7 +77,7 @@ var obj1 = { >num : number >typeof var1 === "string" && var1.length : number >typeof var1 === "string" : boolean ->typeof var1 : string +>typeof var1 : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >var1 : string | number >"string" : "string" >var1.length : number @@ -93,7 +93,7 @@ var obj1 = { >num : number >typeof var2 === "string" && var2.length : number >typeof var2 === "string" : boolean ->typeof var2 : string +>typeof var2 : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >var2 : string | number >"string" : "string" >var2.length : number @@ -114,7 +114,7 @@ var obj1 = { >num : number >typeof var1 === "string" && var1.length : number >typeof var1 === "string" : boolean ->typeof var1 : string +>typeof var1 : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >var1 : string | number >"string" : "string" >var1.length : number @@ -130,7 +130,7 @@ var obj1 = { >num : number >typeof var2 === "string" && var2.length : number >typeof var2 === "string" : boolean ->typeof var2 : string +>typeof var2 : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >var2 : string | number >"string" : "string" >var2.length : number @@ -143,7 +143,7 @@ var obj1 = { >num : number >typeof param === "string" && param.length : number >typeof param === "string" : boolean ->typeof param : string +>typeof param : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >param : string | number >"string" : "string" >param.length : number @@ -157,7 +157,7 @@ strOrNum = typeof obj1.method(strOrNum) === "string" && obj1.method(strOrNum); >strOrNum : string | number >typeof obj1.method(strOrNum) === "string" && obj1.method(strOrNum) : string | number >typeof obj1.method(strOrNum) === "string" : boolean ->typeof obj1.method(strOrNum) : string +>typeof obj1.method(strOrNum) : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >obj1.method(strOrNum) : string | number >obj1.method : (param: string | number) => string | number >obj1 : { method(param: string | number): string | number; prop: string | number; } @@ -176,7 +176,7 @@ strOrNum = typeof obj1.prop === "string" && obj1.prop; >strOrNum : string | number >typeof obj1.prop === "string" && obj1.prop : string >typeof obj1.prop === "string" : boolean ->typeof obj1.prop : string +>typeof obj1.prop : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >obj1.prop : string | number >obj1 : { method(param: string | number): string | number; prop: string | number; } >prop : string | number diff --git a/tests/baselines/reference/typeGuardsOnClassProperty.types b/tests/baselines/reference/typeGuardsOnClassProperty.types index 1b663ef209f..f4c3542344f 100644 --- a/tests/baselines/reference/typeGuardsOnClassProperty.types +++ b/tests/baselines/reference/typeGuardsOnClassProperty.types @@ -22,7 +22,7 @@ class D { return typeof data === "string" ? data : data.join(" "); >typeof data === "string" ? data : data.join(" ") : string >typeof data === "string" : boolean ->typeof data : string +>typeof data : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >data : string | string[] >"string" : "string" >data : string @@ -39,7 +39,7 @@ class D { return typeof this.data === "string" ? this.data : this.data.join(" "); >typeof this.data === "string" ? this.data : this.data.join(" ") : string >typeof this.data === "string" : boolean ->typeof this.data : string +>typeof this.data : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >this.data : string | string[] >this : this >data : string | string[] @@ -81,7 +81,7 @@ var o: { if (typeof o.prop1 === "string" && o.prop1.toLowerCase()) {} >typeof o.prop1 === "string" && o.prop1.toLowerCase() : string >typeof o.prop1 === "string" : boolean ->typeof o.prop1 : string +>typeof o.prop1 : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >o.prop1 : string | number >o : { prop1: string | number; prop2: string | boolean; } >prop1 : string | number @@ -102,7 +102,7 @@ var prop1 = o.prop1; if (typeof prop1 === "string" && prop1.toLocaleLowerCase()) { } >typeof prop1 === "string" && prop1.toLocaleLowerCase() : string >typeof prop1 === "string" : boolean ->typeof prop1 : string +>typeof prop1 : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function" >prop1 : string | number >"string" : "string" >prop1.toLocaleLowerCase() : string diff --git a/tests/baselines/reference/typeOfOperator1.errors.txt b/tests/baselines/reference/typeOfOperator1.errors.txt index 764463a3087..75fc25d243c 100644 --- a/tests/baselines/reference/typeOfOperator1.errors.txt +++ b/tests/baselines/reference/typeOfOperator1.errors.txt @@ -1,4 +1,5 @@ -tests/cases/compiler/typeOfOperator1.ts(3,5): error TS2322: Type 'string' is not assignable to type 'number'. +tests/cases/compiler/typeOfOperator1.ts(3,5): error TS2322: Type '"string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function"' is not assignable to type 'number'. + Type '"string"' is not assignable to type 'number'. ==== tests/cases/compiler/typeOfOperator1.ts (1 errors) ==== @@ -6,4 +7,5 @@ tests/cases/compiler/typeOfOperator1.ts(3,5): error TS2322: Type 'string' is not var y: string = typeof x; var z: number = typeof x; ~ -!!! error TS2322: Type 'string' is not assignable to type 'number'. \ No newline at end of file +!!! error TS2322: Type '"string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function"' is not assignable to type 'number'. +!!! error TS2322: Type '"string"' is not assignable to type 'number'. \ No newline at end of file diff --git a/tests/cases/conformance/expressions/typeGuards/typeGuardOfFormTypeOfOther.ts b/tests/cases/conformance/expressions/typeGuards/typeGuardOfFormTypeOfOther.ts index 44b064c3219..92b3103723e 100644 --- a/tests/cases/conformance/expressions/typeGuards/typeGuardOfFormTypeOfOther.ts +++ b/tests/cases/conformance/expressions/typeGuards/typeGuardOfFormTypeOfOther.ts @@ -36,6 +36,12 @@ if (typeof boolOrC === "Object") { else { var r4: boolean = boolOrC; // boolean } +if (typeof strOrC === "Object" as string) { // comparison is OK with cast + c = strOrC; // error: but no narrowing to C +} +else { + var r5: string = strOrC; // error: no narrowing to string +} if (typeof strOrNumOrBool === "Object") { let q1: {} = strOrNumOrBool; // {} From 01bc4efc82105043cb98e1aa9105354a78ea5424 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Tue, 31 Jan 2017 10:34:44 -0800 Subject: [PATCH 14/58] Add arrayFromMap utility function --- src/compiler/checker.ts | 4 +--- src/compiler/core.ts | 8 ++++++++ 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 47811d6ccaf..ba4e8c6993d 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -14609,9 +14609,7 @@ namespace ts { function checkTypeOfExpression(node: TypeOfExpression): Type { checkExpression(node.expression); - const types: Type[] = []; - typeofEQFacts.forEach((_, s) => types.push(getLiteralTypeForText(TypeFlags.StringLiteral, s))); - return getUnionType(types); + return getUnionType(arrayFromMap(typeofEQFacts.keys(), s => getLiteralTypeForText(TypeFlags.StringLiteral, s))); } function checkVoidExpression(node: VoidExpression): Type { diff --git a/src/compiler/core.ts b/src/compiler/core.ts index de3472afd88..486dd5b42c8 100644 --- a/src/compiler/core.ts +++ b/src/compiler/core.ts @@ -895,6 +895,14 @@ namespace ts { return result; } + export function arrayFromMap(iterator: Iterator, f: (value: T) => U) { + const result: U[] = []; + for (let { value, done } = iterator.next(); !done; { value, done } = iterator.next()) { + result.push(f(value)); + } + return result; + } + /** * Calls `callback` for each entry in the map, returning the first truthy result. * Use `map.forEach` instead for normal iteration. From 2ce64f2bad67b3422423dddc8ad4e3d05030c64f Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Tue, 31 Jan 2017 14:39:10 -0800 Subject: [PATCH 15/58] Create typeof's string literal union type once This changes the print order of string literal unions slightly. I think this is because 'string', 'symbol', etc are added to a union very early on in the creation of the checker. --- src/compiler/checker.ts | 9 ++++++--- .../reference/intersectionTypeNormalization.types | 4 ++-- .../reference/modularizeLibrary_Dom.iterable.types | 4 ++-- 3 files changed, 10 insertions(+), 7 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index ba4e8c6993d..8a5e51dd110 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -326,7 +326,6 @@ namespace ts { "object": TypeFacts.TypeofEQObject, "function": TypeFacts.TypeofEQFunction }); - const typeofNEFacts = createMapFromTemplate({ "string": TypeFacts.TypeofNEString, "number": TypeFacts.TypeofNENumber, @@ -336,7 +335,6 @@ namespace ts { "object": TypeFacts.TypeofNEObject, "function": TypeFacts.TypeofNEFunction }); - const typeofTypesByName = createMapFromTemplate({ "string": stringType, "number": numberType, @@ -344,6 +342,7 @@ namespace ts { "symbol": esSymbolType, "undefined": undefinedType }); + const typeofType = createTypeofType(); let jsxElementType: Type; let _jsxNamespace: string; @@ -1725,6 +1724,10 @@ namespace ts { return type; } + function createTypeofType() { + return getUnionType(arrayFromMap(typeofEQFacts.keys(), s => getLiteralTypeForText(TypeFlags.StringLiteral, s))); + } + // A reserved member name starts with two underscores, but the third character cannot be an underscore // or the @ symbol. A third underscore indicates an escaped form of an identifer that started // with at least two underscores. The @ character indicates that the name is denoted by a well known ES @@ -14609,7 +14612,7 @@ namespace ts { function checkTypeOfExpression(node: TypeOfExpression): Type { checkExpression(node.expression); - return getUnionType(arrayFromMap(typeofEQFacts.keys(), s => getLiteralTypeForText(TypeFlags.StringLiteral, s))); + return typeofType; } function checkVoidExpression(node: VoidExpression): Type { diff --git a/tests/baselines/reference/intersectionTypeNormalization.types b/tests/baselines/reference/intersectionTypeNormalization.types index 3ffe7484afe..7d8ba117eec 100644 --- a/tests/baselines/reference/intersectionTypeNormalization.types +++ b/tests/baselines/reference/intersectionTypeNormalization.types @@ -227,9 +227,9 @@ function getValueAsString(value: IntersectionFail): string { if (value.kind === 'int') { >value.kind === 'int' : boolean ->value.kind : "int" | "string" +>value.kind : "string" | "int" >value : IntersectionFail ->kind : "int" | "string" +>kind : "string" | "int" >'int' : "int" return '' + value.num; diff --git a/tests/baselines/reference/modularizeLibrary_Dom.iterable.types b/tests/baselines/reference/modularizeLibrary_Dom.iterable.types index 054923fb5ee..d681322e2a7 100644 --- a/tests/baselines/reference/modularizeLibrary_Dom.iterable.types +++ b/tests/baselines/reference/modularizeLibrary_Dom.iterable.types @@ -3,9 +3,9 @@ for (const element of document.getElementsByTagName("a")) { >element : HTMLAnchorElement >document.getElementsByTagName("a") : NodeListOf ->document.getElementsByTagName : { (tagname: K): ElementListTagNameMap[K]; (tagname: string): NodeListOf; } +>document.getElementsByTagName : { (tagname: K): ElementListTagNameMap[K]; (tagname: string): NodeListOf; } >document : Document ->getElementsByTagName : { (tagname: K): ElementListTagNameMap[K]; (tagname: string): NodeListOf; } +>getElementsByTagName : { (tagname: K): ElementListTagNameMap[K]; (tagname: string): NodeListOf; } >"a" : "a" element.href; From 3b1b5e241f69bfcf49309094359e2620ada6cd06 Mon Sep 17 00:00:00 2001 From: Mohamed Hegazy Date: Tue, 31 Jan 2017 16:35:30 -0800 Subject: [PATCH 16/58] Add string literal completion for equality expression --- src/services/completions.ts | 24 +++++++++++++++++++ .../fourslash/completionForStringLiteral10.ts | 12 ++++++++++ .../fourslash/completionForStringLiteral8.ts | 12 ++++++++++ 3 files changed, 48 insertions(+) create mode 100644 tests/cases/fourslash/completionForStringLiteral10.ts create mode 100644 tests/cases/fourslash/completionForStringLiteral8.ts diff --git a/src/services/completions.ts b/src/services/completions.ts index 5a08dbcb9c8..5d70b357625 100644 --- a/src/services/completions.ts +++ b/src/services/completions.ts @@ -173,6 +173,11 @@ namespace ts.Completions { // var y = require("/*completion position*/"); return getStringLiteralCompletionEntriesFromModuleNames(node, compilerOptions, host, typeChecker); } + else if (isEqualityExpression(node.parent)) { + // Get all known external module names or complete a path to a module + // i.e. x === '/*completion position' + return getStringLiteralCompletionEntriesFromBinaryExpression(node, node.parent, typeChecker); + } else { const argumentInfo = SignatureHelp.getImmediatelyContainingArgumentInfo(node, position, sourceFile); if (argumentInfo) { @@ -240,6 +245,18 @@ namespace ts.Completions { return undefined; } + function getStringLiteralCompletionEntriesFromBinaryExpression(node: StringLiteral, parent: BinaryExpression, typeChecker: TypeChecker): CompletionInfo | undefined { + const type = typeChecker.getTypeAtLocation(parent.left === node ? parent.right : parent.left); + if (type) { + const entries: CompletionEntry[] = []; + addStringLiteralCompletionsFromType(type, entries, typeChecker); + if (entries.length) { + return { isGlobalCompletion: false, isMemberCompletion: false, isNewIdentifierLocation: false, entries }; + } + } + return undefined; + } + function addStringLiteralCompletionsFromType(type: Type, result: Push, typeChecker: TypeChecker): void { if (type && type.flags & TypeFlags.TypeParameter) { type = typeChecker.getApparentType(type); @@ -1756,4 +1773,11 @@ namespace ts.Completions { catch (e) {} return undefined; } + + function isEqualityExpression(node: Node): node is BinaryExpression { + return isBinaryExpression(node) && (node.operatorToken.kind == SyntaxKind.EqualsEqualsToken || + node.operatorToken.kind === SyntaxKind.ExclamationEqualsToken || + node.operatorToken.kind === SyntaxKind.EqualsEqualsEqualsToken || + node.operatorToken.kind === SyntaxKind.ExclamationEqualsEqualsToken); + } } diff --git a/tests/cases/fourslash/completionForStringLiteral10.ts b/tests/cases/fourslash/completionForStringLiteral10.ts new file mode 100644 index 00000000000..76a98eb732f --- /dev/null +++ b/tests/cases/fourslash/completionForStringLiteral10.ts @@ -0,0 +1,12 @@ +/// + +////type As = 'arf' | 'abacus' | 'abaddon'; +////let a: As; +////if ('/**/' != a + +goTo.marker(); +verify.completionListContains("arf"); +verify.completionListContains("abacus"); +verify.completionListContains("abaddon"); +verify.completionListCount(3); + diff --git a/tests/cases/fourslash/completionForStringLiteral8.ts b/tests/cases/fourslash/completionForStringLiteral8.ts new file mode 100644 index 00000000000..727bdf6e6a4 --- /dev/null +++ b/tests/cases/fourslash/completionForStringLiteral8.ts @@ -0,0 +1,12 @@ +/// + +////type As = 'arf' | 'abacus' | 'abaddon'; +////let a: As; +////if (a === '/**/ + +goTo.marker(); +verify.completionListContains("arf"); +verify.completionListContains("abacus"); +verify.completionListContains("abaddon"); +verify.completionListCount(3); + From 52841924dad0909e1284352d1ab9b14c00437fda Mon Sep 17 00:00:00 2001 From: Mohamed Hegazy Date: Tue, 31 Jan 2017 16:35:30 -0800 Subject: [PATCH 17/58] Support string literal completion in case labels --- src/services/completions.ts | 28 ++++++++----------- .../fourslash/completionForStringLiteral11.ts | 14 ++++++++++ 2 files changed, 25 insertions(+), 17 deletions(-) create mode 100644 tests/cases/fourslash/completionForStringLiteral11.ts diff --git a/src/services/completions.ts b/src/services/completions.ts index 5d70b357625..4c882c9b6b6 100644 --- a/src/services/completions.ts +++ b/src/services/completions.ts @@ -174,9 +174,16 @@ namespace ts.Completions { return getStringLiteralCompletionEntriesFromModuleNames(node, compilerOptions, host, typeChecker); } else if (isEqualityExpression(node.parent)) { - // Get all known external module names or complete a path to a module + // Get completions from the type of the other operand + // i.e. switch (a) { + // case '/*completion position*/' + // } + return getStringLiteralCompletionEntriesFromType(typeChecker.getTypeAtLocation(node.parent.left === node ? node.parent.right : node.parent.left), typeChecker); + } + else if (isCaseOrDefaultClause(node.parent)) { + // Get completions from the type of the switch expression // i.e. x === '/*completion position' - return getStringLiteralCompletionEntriesFromBinaryExpression(node, node.parent, typeChecker); + return getStringLiteralCompletionEntriesFromType(typeChecker.getTypeAtLocation((node.parent.parent.parent).expression), typeChecker); } else { const argumentInfo = SignatureHelp.getImmediatelyContainingArgumentInfo(node, position, sourceFile); @@ -189,7 +196,7 @@ namespace ts.Completions { // Get completion for string literal from string literal type // i.e. var x: "hi" | "hello" = "/*completion position*/" - return getStringLiteralCompletionEntriesFromContextualType(node, typeChecker); + return getStringLiteralCompletionEntriesFromType(typeChecker.getContextualType(node), typeChecker); } } @@ -233,20 +240,7 @@ namespace ts.Completions { return undefined; } - function getStringLiteralCompletionEntriesFromContextualType(node: StringLiteral, typeChecker: TypeChecker): CompletionInfo | undefined { - const type = typeChecker.getContextualType(node); - if (type) { - const entries: CompletionEntry[] = []; - addStringLiteralCompletionsFromType(type, entries, typeChecker); - if (entries.length) { - return { isGlobalCompletion: false, isMemberCompletion: false, isNewIdentifierLocation: false, entries }; - } - } - return undefined; - } - - function getStringLiteralCompletionEntriesFromBinaryExpression(node: StringLiteral, parent: BinaryExpression, typeChecker: TypeChecker): CompletionInfo | undefined { - const type = typeChecker.getTypeAtLocation(parent.left === node ? parent.right : parent.left); + function getStringLiteralCompletionEntriesFromType(type: Type, typeChecker: TypeChecker): CompletionInfo | undefined { if (type) { const entries: CompletionEntry[] = []; addStringLiteralCompletionsFromType(type, entries, typeChecker); diff --git a/tests/cases/fourslash/completionForStringLiteral11.ts b/tests/cases/fourslash/completionForStringLiteral11.ts new file mode 100644 index 00000000000..f6acac28a65 --- /dev/null +++ b/tests/cases/fourslash/completionForStringLiteral11.ts @@ -0,0 +1,14 @@ +/// + +////type As = 'arf' | 'abacus' | 'abaddon'; +////let a: As; +////switch (a) { +//// case '/**/ +////} + +goTo.marker(); +verify.completionListContains("arf"); +verify.completionListContains("abacus"); +verify.completionListContains("abaddon"); +verify.completionListCount(3); + From a39c14ec2e85bd61cd9c1820232e6840a5ffe07d Mon Sep 17 00:00:00 2001 From: Mohamed Hegazy Date: Tue, 31 Jan 2017 21:34:25 -0800 Subject: [PATCH 18/58] Factor kind check to a separate function --- src/services/completions.ts | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/services/completions.ts b/src/services/completions.ts index 4c882c9b6b6..df78ab931d1 100644 --- a/src/services/completions.ts +++ b/src/services/completions.ts @@ -1769,9 +1769,13 @@ namespace ts.Completions { } function isEqualityExpression(node: Node): node is BinaryExpression { - return isBinaryExpression(node) && (node.operatorToken.kind == SyntaxKind.EqualsEqualsToken || - node.operatorToken.kind === SyntaxKind.ExclamationEqualsToken || - node.operatorToken.kind === SyntaxKind.EqualsEqualsEqualsToken || - node.operatorToken.kind === SyntaxKind.ExclamationEqualsEqualsToken); + return isBinaryExpression(node) && isEqualityOperatorKind(node.operatorToken.kind); + } + + function isEqualityOperatorKind(kind: SyntaxKind) { + return kind == SyntaxKind.EqualsEqualsToken || + kind === SyntaxKind.ExclamationEqualsToken || + kind === SyntaxKind.EqualsEqualsEqualsToken || + kind === SyntaxKind.ExclamationEqualsEqualsToken; } } From 15c6022e40eae1549e3aa669f1819016cd90fcdb Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Wed, 1 Feb 2017 09:32:33 -0800 Subject: [PATCH 19/58] Fix typo causing bug --- src/compiler/checker.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 26c27cb3be2..de7e9a9387f 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -4929,7 +4929,7 @@ namespace ts { } function getApparentTypeOfIntersectionType(type: IntersectionType) { - return type.resolvedIndexType || (type.resolvedApparentType = getTypeWithThisArgument(type, type)); + return type.resolvedApparentType || (type.resolvedApparentType = getTypeWithThisArgument(type, type)); } /** From 34ec8956421bdedbc53277e2d4c7fcb35ccf9e4d Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Wed, 1 Feb 2017 09:47:30 -0800 Subject: [PATCH 20/58] Add regression test --- .../types/keyof/keyofAndIndexedAccess.ts | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/tests/cases/conformance/types/keyof/keyofAndIndexedAccess.ts b/tests/cases/conformance/types/keyof/keyofAndIndexedAccess.ts index a8a5acd450f..70b70dff6ea 100644 --- a/tests/cases/conformance/types/keyof/keyofAndIndexedAccess.ts +++ b/tests/cases/conformance/types/keyof/keyofAndIndexedAccess.ts @@ -527,3 +527,30 @@ class Form { this.childFormFactories[prop](value) } } + +// Repro from #13787 + +class SampleClass

{ + public props: Readonly

; + constructor(props: P) { + this.props = Object.freeze(props); + } +} + +interface Foo { + foo: string; +} + +declare function merge(obj1: T, obj2: U): T & U; + +class AnotherSampleClass extends SampleClass { + constructor(props: T) { + const foo: Foo = { foo: "bar" }; + super(merge(props, foo)); + } + + public brokenMethod() { + this.props.foo.concat; + } +} +new AnotherSampleClass({}); From 97828b4b9c79efa087c857b3492cf2373ae8699b Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Wed, 1 Feb 2017 09:47:37 -0800 Subject: [PATCH 21/58] Accept new baselines --- .../reference/keyofAndIndexedAccess.js | 60 ++++++++++++ .../reference/keyofAndIndexedAccess.symbols | 83 +++++++++++++++++ .../reference/keyofAndIndexedAccess.types | 91 +++++++++++++++++++ 3 files changed, 234 insertions(+) diff --git a/tests/baselines/reference/keyofAndIndexedAccess.js b/tests/baselines/reference/keyofAndIndexedAccess.js index 62b848e97df..2b1b22d3595 100644 --- a/tests/baselines/reference/keyofAndIndexedAccess.js +++ b/tests/baselines/reference/keyofAndIndexedAccess.js @@ -526,6 +526,33 @@ class Form { this.childFormFactories[prop](value) } } + +// Repro from #13787 + +class SampleClass

{ + public props: Readonly

; + constructor(props: P) { + this.props = Object.freeze(props); + } +} + +interface Foo { + foo: string; +} + +declare function merge(obj1: T, obj2: U): T & U; + +class AnotherSampleClass extends SampleClass { + constructor(props: T) { + const foo: Foo = { foo: "bar" }; + super(merge(props, foo)); + } + + public brokenMethod() { + this.props.foo.concat; + } +} +new AnotherSampleClass({}); //// [keyofAndIndexedAccess.js] @@ -881,6 +908,27 @@ var Form = (function () { }; return Form; }()); +// Repro from #13787 +var SampleClass = (function () { + function SampleClass(props) { + this.props = Object.freeze(props); + } + return SampleClass; +}()); +var AnotherSampleClass = (function (_super) { + __extends(AnotherSampleClass, _super); + function AnotherSampleClass(props) { + var _this = this; + var foo = { foo: "bar" }; + _this = _super.call(this, merge(props, foo)) || this; + return _this; + } + AnotherSampleClass.prototype.brokenMethod = function () { + this.props.foo.concat; + }; + return AnotherSampleClass; +}(SampleClass)); +new AnotherSampleClass({}); //// [keyofAndIndexedAccess.d.ts] @@ -1127,3 +1175,15 @@ declare class Form { private childFormFactories; set(prop: K, value: T[K]): void; } +declare class SampleClass

{ + props: Readonly

; + constructor(props: P); +} +interface Foo { + foo: string; +} +declare function merge(obj1: T, obj2: U): T & U; +declare class AnotherSampleClass extends SampleClass { + constructor(props: T); + brokenMethod(): void; +} diff --git a/tests/baselines/reference/keyofAndIndexedAccess.symbols b/tests/baselines/reference/keyofAndIndexedAccess.symbols index 54fff19f428..f6425b5ed0e 100644 --- a/tests/baselines/reference/keyofAndIndexedAccess.symbols +++ b/tests/baselines/reference/keyofAndIndexedAccess.symbols @@ -1880,3 +1880,86 @@ class Form { } } +// Repro from #13787 + +class SampleClass

{ +>SampleClass : Symbol(SampleClass, Decl(keyofAndIndexedAccess.ts, 526, 1)) +>P : Symbol(P, Decl(keyofAndIndexedAccess.ts, 530, 18)) + + public props: Readonly

; +>props : Symbol(SampleClass.props, Decl(keyofAndIndexedAccess.ts, 530, 22)) +>Readonly : Symbol(Readonly, Decl(lib.d.ts, --, --)) +>P : Symbol(P, Decl(keyofAndIndexedAccess.ts, 530, 18)) + + constructor(props: P) { +>props : Symbol(props, Decl(keyofAndIndexedAccess.ts, 532, 16)) +>P : Symbol(P, Decl(keyofAndIndexedAccess.ts, 530, 18)) + + this.props = Object.freeze(props); +>this.props : Symbol(SampleClass.props, Decl(keyofAndIndexedAccess.ts, 530, 22)) +>this : Symbol(SampleClass, Decl(keyofAndIndexedAccess.ts, 526, 1)) +>props : Symbol(SampleClass.props, Decl(keyofAndIndexedAccess.ts, 530, 22)) +>Object.freeze : Symbol(ObjectConstructor.freeze, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) +>Object : Symbol(Object, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) +>freeze : Symbol(ObjectConstructor.freeze, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) +>props : Symbol(props, Decl(keyofAndIndexedAccess.ts, 532, 16)) + } +} + +interface Foo { +>Foo : Symbol(Foo, Decl(keyofAndIndexedAccess.ts, 535, 1)) + + foo: string; +>foo : Symbol(Foo.foo, Decl(keyofAndIndexedAccess.ts, 537, 15)) +} + +declare function merge(obj1: T, obj2: U): T & U; +>merge : Symbol(merge, Decl(keyofAndIndexedAccess.ts, 539, 1)) +>T : Symbol(T, Decl(keyofAndIndexedAccess.ts, 541, 23)) +>U : Symbol(U, Decl(keyofAndIndexedAccess.ts, 541, 25)) +>obj1 : Symbol(obj1, Decl(keyofAndIndexedAccess.ts, 541, 29)) +>T : Symbol(T, Decl(keyofAndIndexedAccess.ts, 541, 23)) +>obj2 : Symbol(obj2, Decl(keyofAndIndexedAccess.ts, 541, 37)) +>U : Symbol(U, Decl(keyofAndIndexedAccess.ts, 541, 25)) +>T : Symbol(T, Decl(keyofAndIndexedAccess.ts, 541, 23)) +>U : Symbol(U, Decl(keyofAndIndexedAccess.ts, 541, 25)) + +class AnotherSampleClass extends SampleClass { +>AnotherSampleClass : Symbol(AnotherSampleClass, Decl(keyofAndIndexedAccess.ts, 541, 54)) +>T : Symbol(T, Decl(keyofAndIndexedAccess.ts, 543, 25)) +>SampleClass : Symbol(SampleClass, Decl(keyofAndIndexedAccess.ts, 526, 1)) +>T : Symbol(T, Decl(keyofAndIndexedAccess.ts, 543, 25)) +>Foo : Symbol(Foo, Decl(keyofAndIndexedAccess.ts, 535, 1)) + + constructor(props: T) { +>props : Symbol(props, Decl(keyofAndIndexedAccess.ts, 544, 16)) +>T : Symbol(T, Decl(keyofAndIndexedAccess.ts, 543, 25)) + + const foo: Foo = { foo: "bar" }; +>foo : Symbol(foo, Decl(keyofAndIndexedAccess.ts, 545, 13)) +>Foo : Symbol(Foo, Decl(keyofAndIndexedAccess.ts, 535, 1)) +>foo : Symbol(foo, Decl(keyofAndIndexedAccess.ts, 545, 26)) + + super(merge(props, foo)); +>super : Symbol(SampleClass, Decl(keyofAndIndexedAccess.ts, 526, 1)) +>merge : Symbol(merge, Decl(keyofAndIndexedAccess.ts, 539, 1)) +>props : Symbol(props, Decl(keyofAndIndexedAccess.ts, 544, 16)) +>foo : Symbol(foo, Decl(keyofAndIndexedAccess.ts, 545, 13)) + } + + public brokenMethod() { +>brokenMethod : Symbol(AnotherSampleClass.brokenMethod, Decl(keyofAndIndexedAccess.ts, 547, 5)) + + this.props.foo.concat; +>this.props.foo.concat : Symbol(String.concat, Decl(lib.d.ts, --, --)) +>this.props.foo : Symbol(foo) +>this.props : Symbol(SampleClass.props, Decl(keyofAndIndexedAccess.ts, 530, 22)) +>this : Symbol(AnotherSampleClass, Decl(keyofAndIndexedAccess.ts, 541, 54)) +>props : Symbol(SampleClass.props, Decl(keyofAndIndexedAccess.ts, 530, 22)) +>foo : Symbol(foo) +>concat : Symbol(String.concat, Decl(lib.d.ts, --, --)) + } +} +new AnotherSampleClass({}); +>AnotherSampleClass : Symbol(AnotherSampleClass, Decl(keyofAndIndexedAccess.ts, 541, 54)) + diff --git a/tests/baselines/reference/keyofAndIndexedAccess.types b/tests/baselines/reference/keyofAndIndexedAccess.types index e987ee9043b..86469efc284 100644 --- a/tests/baselines/reference/keyofAndIndexedAccess.types +++ b/tests/baselines/reference/keyofAndIndexedAccess.types @@ -2204,3 +2204,94 @@ class Form { } } +// Repro from #13787 + +class SampleClass

{ +>SampleClass : SampleClass

+>P : P + + public props: Readonly

; +>props : Readonly

+>Readonly : Readonly +>P : P + + constructor(props: P) { +>props : P +>P : P + + this.props = Object.freeze(props); +>this.props = Object.freeze(props) : Readonly

+>this.props : Readonly

+>this : this +>props : Readonly

+>Object.freeze(props) : Readonly

+>Object.freeze : { (a: T[]): ReadonlyArray; (f: T): T; (o: T): Readonly; } +>Object : ObjectConstructor +>freeze : { (a: T[]): ReadonlyArray; (f: T): T; (o: T): Readonly; } +>props : P + } +} + +interface Foo { +>Foo : Foo + + foo: string; +>foo : string +} + +declare function merge(obj1: T, obj2: U): T & U; +>merge : (obj1: T, obj2: U) => T & U +>T : T +>U : U +>obj1 : T +>T : T +>obj2 : U +>U : U +>T : T +>U : U + +class AnotherSampleClass extends SampleClass { +>AnotherSampleClass : AnotherSampleClass +>T : T +>SampleClass : SampleClass +>T : T +>Foo : Foo + + constructor(props: T) { +>props : T +>T : T + + const foo: Foo = { foo: "bar" }; +>foo : Foo +>Foo : Foo +>{ foo: "bar" } : { foo: string; } +>foo : string +>"bar" : "bar" + + super(merge(props, foo)); +>super(merge(props, foo)) : void +>super : typeof SampleClass +>merge(props, foo) : T & Foo +>merge : (obj1: T, obj2: U) => T & U +>props : T +>foo : Foo + } + + public brokenMethod() { +>brokenMethod : () => void + + this.props.foo.concat; +>this.props.foo.concat : (...strings: string[]) => string +>this.props.foo : (T & Foo)["foo"] +>this.props : Readonly +>this : this +>props : Readonly +>foo : (T & Foo)["foo"] +>concat : (...strings: string[]) => string + } +} +new AnotherSampleClass({}); +>new AnotherSampleClass({}) : AnotherSampleClass<{}> +>AnotherSampleClass : typeof AnotherSampleClass +>{} : {} + From 86b3c14099464ec43aabb961296f9098480766f6 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Wed, 1 Feb 2017 11:36:33 -0800 Subject: [PATCH 22/58] Consider 'object' a valid base type + apparent type of 'object' is {} --- src/compiler/checker.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index de7e9a9387f..b5306771dd7 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -3991,7 +3991,7 @@ namespace ts { // A valid base type is any non-generic object type or intersection of non-generic // object types. function isValidBaseType(type: Type): boolean { - return type.flags & TypeFlags.Object && !isGenericMappedType(type) || + return type.flags & (TypeFlags.Object | TypeFlags.NonPrimitive) && !isGenericMappedType(type) || type.flags & TypeFlags.Intersection && !forEach((type).types, t => !isValidBaseType(t)); } @@ -4944,7 +4944,7 @@ namespace ts { t.flags & TypeFlags.NumberLike ? globalNumberType : t.flags & TypeFlags.BooleanLike ? globalBooleanType : t.flags & TypeFlags.ESSymbol ? getGlobalESSymbolType() : - t.flags & TypeFlags.NonPrimitive ? globalObjectType : + t.flags & TypeFlags.NonPrimitive ? emptyObjectType : t; } From b6d612980c76f545d75cf669336457a33b85dec6 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Wed, 1 Feb 2017 11:37:11 -0800 Subject: [PATCH 23/58] Accept baseline change for apparent type --- tests/baselines/reference/nonPrimitiveAssignError.errors.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/baselines/reference/nonPrimitiveAssignError.errors.txt b/tests/baselines/reference/nonPrimitiveAssignError.errors.txt index a9bfaaa4a8a..f8c4450f3aa 100644 --- a/tests/baselines/reference/nonPrimitiveAssignError.errors.txt +++ b/tests/baselines/reference/nonPrimitiveAssignError.errors.txt @@ -1,5 +1,5 @@ tests/cases/conformance/types/nonPrimitive/nonPrimitiveAssignError.ts(5,1): error TS2322: Type 'object' is not assignable to type '{ foo: string; }'. - Property 'foo' is missing in type 'Object'. + Property 'foo' is missing in type '{}'. tests/cases/conformance/types/nonPrimitive/nonPrimitiveAssignError.ts(13,1): error TS2322: Type 'number' is not assignable to type 'object'. tests/cases/conformance/types/nonPrimitive/nonPrimitiveAssignError.ts(14,1): error TS2322: Type 'true' is not assignable to type 'object'. tests/cases/conformance/types/nonPrimitive/nonPrimitiveAssignError.ts(15,1): error TS2322: Type 'string' is not assignable to type 'object'. @@ -16,7 +16,7 @@ tests/cases/conformance/types/nonPrimitive/nonPrimitiveAssignError.ts(19,1): err y = a; // expect error ~ !!! error TS2322: Type 'object' is not assignable to type '{ foo: string; }'. -!!! error TS2322: Property 'foo' is missing in type 'Object'. +!!! error TS2322: Property 'foo' is missing in type '{}'. a = x; a = y; From a8de5ce836e54c4d8d3713a6db789b27402c399c Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Wed, 1 Feb 2017 11:37:24 -0800 Subject: [PATCH 24/58] Add regression test --- tests/cases/conformance/classes/mixinClassesAnonymous.ts | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/tests/cases/conformance/classes/mixinClassesAnonymous.ts b/tests/cases/conformance/classes/mixinClassesAnonymous.ts index 24289b61e3e..0e422888087 100644 --- a/tests/cases/conformance/classes/mixinClassesAnonymous.ts +++ b/tests/cases/conformance/classes/mixinClassesAnonymous.ts @@ -54,3 +54,11 @@ class Thing3 extends Thing2 { this.print(); } } + +// Repro from #13805 + +const Timestamped = >(Base: CT) => { + return class extends Base { + timestamp = new Date(); + }; +} From 3a0a58d2e2274408788ff98246b001b176710617 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Wed, 1 Feb 2017 11:37:33 -0800 Subject: [PATCH 25/58] Accept new baselines --- .../reference/mixinClassesAnonymous.js | 20 +++++++++++++++++ .../reference/mixinClassesAnonymous.symbols | 19 ++++++++++++++++ .../reference/mixinClassesAnonymous.types | 22 +++++++++++++++++++ 3 files changed, 61 insertions(+) diff --git a/tests/baselines/reference/mixinClassesAnonymous.js b/tests/baselines/reference/mixinClassesAnonymous.js index c7b8ab5fd63..aa148c25acf 100644 --- a/tests/baselines/reference/mixinClassesAnonymous.js +++ b/tests/baselines/reference/mixinClassesAnonymous.js @@ -55,6 +55,14 @@ class Thing3 extends Thing2 { this.print(); } } + +// Repro from #13805 + +const Timestamped = >(Base: CT) => { + return class extends Base { + timestamp = new Date(); + }; +} //// [mixinClassesAnonymous.js] @@ -138,3 +146,15 @@ var Thing3 = (function (_super) { }; return Thing3; }(Thing2)); +// Repro from #13805 +var Timestamped = function (Base) { + return (function (_super) { + __extends(class_2, _super); + function class_2() { + var _this = _super !== null && _super.apply(this, arguments) || this; + _this.timestamp = new Date(); + return _this; + } + return class_2; + }(Base)); +}; diff --git a/tests/baselines/reference/mixinClassesAnonymous.symbols b/tests/baselines/reference/mixinClassesAnonymous.symbols index 204d9c589fd..bd709501f31 100644 --- a/tests/baselines/reference/mixinClassesAnonymous.symbols +++ b/tests/baselines/reference/mixinClassesAnonymous.symbols @@ -167,3 +167,22 @@ class Thing3 extends Thing2 { } } +// Repro from #13805 + +const Timestamped = >(Base: CT) => { +>Timestamped : Symbol(Timestamped, Decl(mixinClassesAnonymous.ts, 59, 5)) +>CT : Symbol(CT, Decl(mixinClassesAnonymous.ts, 59, 21)) +>Constructor : Symbol(Constructor, Decl(mixinClassesAnonymous.ts, 0, 0)) +>Base : Symbol(Base, Decl(mixinClassesAnonymous.ts, 59, 53)) +>CT : Symbol(CT, Decl(mixinClassesAnonymous.ts, 59, 21)) + + return class extends Base { +>Base : Symbol(Base, Decl(mixinClassesAnonymous.ts, 59, 53)) + + timestamp = new Date(); +>timestamp : Symbol((Anonymous class).timestamp, Decl(mixinClassesAnonymous.ts, 60, 31)) +>Date : Symbol(Date, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --)) + + }; +} + diff --git a/tests/baselines/reference/mixinClassesAnonymous.types b/tests/baselines/reference/mixinClassesAnonymous.types index 54b1c2c3819..516b15af2f3 100644 --- a/tests/baselines/reference/mixinClassesAnonymous.types +++ b/tests/baselines/reference/mixinClassesAnonymous.types @@ -198,3 +198,25 @@ class Thing3 extends Thing2 { } } +// Repro from #13805 + +const Timestamped = >(Base: CT) => { +>Timestamped : >(Base: CT) => { new (...args: any[]): (Anonymous class); prototype: .(Anonymous class); } & CT +>>(Base: CT) => { return class extends Base { timestamp = new Date(); };} : >(Base: CT) => { new (...args: any[]): (Anonymous class); prototype: .(Anonymous class); } & CT +>CT : CT +>Constructor : Constructor +>Base : CT +>CT : CT + + return class extends Base { +>class extends Base { timestamp = new Date(); } : { new (...args: any[]): (Anonymous class); prototype: .(Anonymous class); } & CT +>Base : object + + timestamp = new Date(); +>timestamp : Date +>new Date() : Date +>Date : DateConstructor + + }; +} + From d23f692734a38ee6c5a7764c432f65c4e4cb7564 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Wed, 1 Feb 2017 13:11:16 -0800 Subject: [PATCH 26/58] rename arrayFromMap -> convertToArray --- src/compiler/checker.ts | 2 +- src/compiler/core.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 8a5e51dd110..69d019688b1 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -1725,7 +1725,7 @@ namespace ts { } function createTypeofType() { - return getUnionType(arrayFromMap(typeofEQFacts.keys(), s => getLiteralTypeForText(TypeFlags.StringLiteral, s))); + return getUnionType(convertToArray(typeofEQFacts.keys(), s => getLiteralTypeForText(TypeFlags.StringLiteral, s))); } // A reserved member name starts with two underscores, but the third character cannot be an underscore diff --git a/src/compiler/core.ts b/src/compiler/core.ts index 486dd5b42c8..d11f9925c05 100644 --- a/src/compiler/core.ts +++ b/src/compiler/core.ts @@ -895,7 +895,7 @@ namespace ts { return result; } - export function arrayFromMap(iterator: Iterator, f: (value: T) => U) { + export function convertToArray(iterator: Iterator, f: (value: T) => U) { const result: U[] = []; for (let { value, done } = iterator.next(); !done; { value, done } = iterator.next()) { result.push(f(value)); From f02ce1f6a02661da69aade37d9d167274c23dad4 Mon Sep 17 00:00:00 2001 From: Ron Buckton Date: Wed, 1 Feb 2017 15:22:35 -0800 Subject: [PATCH 27/58] PR Feedback --- src/compiler/comments.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/compiler/comments.ts b/src/compiler/comments.ts index f69b4c546a0..200158c2f5c 100644 --- a/src/compiler/comments.ts +++ b/src/compiler/comments.ts @@ -11,7 +11,7 @@ namespace ts { emitTrailingCommentsOfPosition(pos: number): void; } - export function createCommentWriter(printerOptions: PrinterOptions, emitPos: (pos: number) => void): CommentWriter { + export function createCommentWriter(printerOptions: PrinterOptions, emitPos: ((pos: number) => void) | undefined): CommentWriter { const extendedDiagnostics = printerOptions.extendedDiagnostics; const newLine = getNewLineCharacter(printerOptions); let writer: EmitTextWriter; From 984541316ac586bc9fdd385400b8858122a16baf Mon Sep 17 00:00:00 2001 From: Ron Buckton Date: Wed, 1 Feb 2017 16:16:04 -0800 Subject: [PATCH 28/58] Added comments and a few Debug assertions --- src/compiler/emitter.ts | 15 ++++++++++ src/compiler/types.ts | 66 +++++++++++++++++++++++++++++++++++++++-- 2 files changed, 78 insertions(+), 3 deletions(-) diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index f20a7944a0f..8c6868555f2 100644 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -236,6 +236,21 @@ namespace ts { }; function printNode(hint: EmitHint, node: Node, sourceFile: SourceFile): string { + switch (hint) { + case EmitHint.SourceFile: + Debug.assert(isSourceFile(node), "Expected a SourceFile node."); + break; + case EmitHint.IdentifierName: + Debug.assert(isIdentifier(node), "Expected an Identifier node."); + break; + case EmitHint.Expression: + Debug.assert(isExpression(node), "Expected an Expression node."); + break; + } + switch (node.kind) { + case SyntaxKind.SourceFile: return printFile(node); + case SyntaxKind.Bundle: return printBundle(node); + } writeNode(hint, node, sourceFile, beginPrint()); return endPrint(); } diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 03098fd4129..8660e6138cd 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -3912,8 +3912,27 @@ export type Transformer = (context: TransformationContext) => (node: SourceFile) => SourceFile; export interface Printer { + /** + * Print a node and its subtree as-is, without any emit transformations. + * @param hint A value indicating the purpose of a node. This is primarily used to + * distinguish between an `Identifier` used in an expression position, versus an + * `Identifier` used as an `IdentifierName` as part of a declaration. For most nodes you + * should just pass `Unspecified`. + * @param node The node to print. The node and its subtree are printed as-is, without any + * emit transformations. + * @param sourceFile A source file that provides context for the node. The source text of + * the file is used to emit the original source content for literals and identifiers, while + * the identifiers of the source file are used when generating unique names to avoid + * collisions. + */ printNode(hint: EmitHint, node: Node, sourceFile: SourceFile): string; + /** + * Prints a source file as-is, without any emit transformations. + */ printFile(sourceFile: SourceFile): string; + /** + * Prints a bundle of source files as-is, without any emit transformations. + */ printBundle(bundle: Bundle): string; /*@internal*/ writeNode(hint: EmitHint, node: Node, sourceFile: SourceFile, writer: EmitTextWriter): void; /*@internal*/ writeFile(sourceFile: SourceFile, writer: EmitTextWriter): void; @@ -3921,9 +3940,50 @@ } export interface PrintHandlers { - hasGlobalName?: (name: string) => boolean; - onEmitNode?: (hint: EmitHint, node: Node, emitCallback: (hint: EmitHint, node: Node) => void) => void; - onSubstituteNode?: (hint: EmitHint, node: Node, emitCallback: (hint: EmitHint, node: Node) => void) => void; + /** + * A hook used by the Printer when generating unique names to avoid collisions with + * globally defined names that exist outside of the current source file. + */ + hasGlobalName?(name: string): boolean; + /** + * A hook used by the Printer to provide notifications prior to emitting a node. A + * compatible implementation **must** invoke `emitCallback` with the provided `hint` and + * `node` values. + * @param hint A hint indicating the intended purpose of the node. + * @param node The node to emit. + * @param emitCallback A callback that, when invoked, will emit the node. + * @example + * ```ts + * var printer = createPrinter(printerOptions, { + * onEmitNode(hint, node, emitCallback) { + * // set up or track state prior to emitting the node... + * emitCallback(hint, node); + * // restore state after emitting the node... + * } + * }); + * ``` + */ + onEmitNode?(hint: EmitHint, node: Node, emitCallback: (hint: EmitHint, node: Node) => void): void; + /** + * A hook used by the Printer to perform just-in-time substitution of a node. This is + * primarily used by node transformations that need to substitute one node for another, + * such as replacing `myExportedVar` with `exports.myExportedVar`. A compatible + * implementation **must** invoke `emitCallback` eith the provided `hint` and either + * the provided `node`, or its substitute. + * @param hint A hint indicating the intended purpose of the node. + * @param node The node to emit. + * @param emitCallback A callback that, when invoked, will emit the node. + * @example + * ```ts + * var printer = createPrinter(printerOptions, { + * onSubstituteNode(hint, node, emitCallback) { + * // perform substitution if necessary... + * emitCallback(hint, node); + * } + * }); + * ``` + */ + onSubstituteNode?(hint: EmitHint, node: Node, emitCallback: (hint: EmitHint, node: Node) => void): void; /*@internal*/ onEmitSourceMapOfNode?: (hint: EmitHint, node: Node, emitCallback: (hint: EmitHint, node: Node) => void) => void; /*@internal*/ onEmitSourceMapOfToken?: (node: Node, token: SyntaxKind, pos: number, emitCallback: (token: SyntaxKind, pos: number) => number) => number; /*@internal*/ onEmitSourceMapOfPosition?: (pos: number) => void; From ff4c72de00335109af3d31094139b23be840892e Mon Sep 17 00:00:00 2001 From: Ron Buckton Date: Wed, 1 Feb 2017 16:36:10 -0800 Subject: [PATCH 29/58] Make most current Node factory functions public --- src/compiler/factory.ts | 2224 ++++++++++---------- src/compiler/program.ts | 9 +- src/compiler/transformers/destructuring.ts | 23 +- src/compiler/transformers/es2015.ts | 363 ++-- src/compiler/transformers/es2016.ts | 48 +- src/compiler/transformers/es2017.ts | 41 +- src/compiler/transformers/es5.ts | 4 +- src/compiler/transformers/esnext.ts | 28 +- src/compiler/transformers/generators.ts | 216 +- src/compiler/transformers/jsx.ts | 6 +- src/compiler/transformers/module/es2015.ts | 2 +- src/compiler/transformers/module/module.ts | 450 ++-- src/compiler/transformers/module/system.ts | 141 +- src/compiler/transformers/ts.ts | 257 ++- src/compiler/types.ts | 6 +- src/compiler/utilities.ts | 8 + src/compiler/visitor.ts | 28 +- 17 files changed, 2056 insertions(+), 1798 deletions(-) diff --git a/src/compiler/factory.ts b/src/compiler/factory.ts index f2a8de3a93b..ec1e0dafb79 100644 --- a/src/compiler/factory.ts +++ b/src/compiler/factory.ts @@ -1,28 +1,18 @@ /// /// -/* @internal */ namespace ts { - let NodeConstructor: new (kind: SyntaxKind, pos: number, end: number) => Node; - let SourceFileConstructor: new (kind: SyntaxKind, pos: number, end: number) => Node; - - function createNode(kind: SyntaxKind, location?: TextRange, flags?: NodeFlags): Node { - const ConstructorForKind = kind === SyntaxKind.SourceFile - ? (SourceFileConstructor || (SourceFileConstructor = objectAllocator.getSourceFileConstructor())) - : (NodeConstructor || (NodeConstructor = objectAllocator.getNodeConstructor())); - - const node = location - ? new ConstructorForKind(kind, location.pos, location.end) - : new ConstructorForKind(kind, /*pos*/ -1, /*end*/ -1); - - node.flags = flags | NodeFlags.Synthesized; - + function createSynthesizedNode(kind: SyntaxKind): Node { + const node = createNode(kind, -1, -1); + node.flags |= NodeFlags.Synthesized; return node; } + /* @internal */ export function updateNode(updated: T, original: T): T { if (updated !== original) { setOriginalNode(updated, original); + setTextRange(updated, original); if (original.startsOnNewLine) { updated.startsOnNewLine = true; } @@ -31,7 +21,10 @@ namespace ts { return updated; } - export function createNodeArray(elements?: T[], location?: TextRange, hasTrailingComma?: boolean): NodeArray { + /** + * Make `elements` into a `NodeArray`. If `elements` is `undefined`, returns an empty `NodeArray`. + */ + export function createNodeArray(elements?: T[], hasTrailingComma?: boolean): NodeArray { if (elements) { if (isNodeArray(elements)) { return elements; @@ -42,40 +35,22 @@ namespace ts { } const array = >elements; - if (location) { - array.pos = location.pos; - array.end = location.end; - } - else { - array.pos = -1; - array.end = -1; - } - - if (hasTrailingComma) { - array.hasTrailingComma = true; - } - + array.pos = -1; + array.end = -1; + array.hasTrailingComma = hasTrailingComma; return array; } - export function createSynthesizedNode(kind: SyntaxKind, startsOnNewLine?: boolean): Node { - const node = createNode(kind, /*location*/ undefined); - node.startsOnNewLine = startsOnNewLine; - return node; - } - - export function createSynthesizedNodeArray(elements?: T[]): NodeArray { - return createNodeArray(elements, /*location*/ undefined); - } - /** * Creates a shallow, memberwise clone of a node with no source map location. */ + /* @internal */ export function getSynthesizedClone(node: T): T { // We don't use "clone" from core.ts here, as we need to preserve the prototype chain of // the original node. We also need to exclude specific properties and only include own- // properties (to skip members already defined on the shared prototype). - const clone = createNode(node.kind, /*location*/ undefined, node.flags); + const clone = createSynthesizedNode(node.kind); + clone.flags |= node.flags; setOriginalNode(clone, node); for (const key in node) { @@ -89,63 +64,62 @@ namespace ts { return clone; } - /** - * Creates a shallow, memberwise clone of a node for mutation. - */ - export function getMutableClone(node: T): T { - const clone = getSynthesizedClone(node); - clone.pos = node.pos; - clone.end = node.end; - clone.parent = node.parent; - return clone; - } - // Literals - export function createLiteral(textSource: StringLiteral | NumericLiteral | Identifier, location?: TextRange): StringLiteral; - export function createLiteral(value: string, location?: TextRange): StringLiteral; - export function createLiteral(value: number, location?: TextRange): NumericLiteral; - export function createLiteral(value: boolean, location?: TextRange): BooleanLiteral; - export function createLiteral(value: string | number | boolean, location?: TextRange): PrimaryExpression; - export function createLiteral(value: string | number | boolean | StringLiteral | NumericLiteral | Identifier, location?: TextRange): PrimaryExpression { + export function createLiteral(value: string): StringLiteral; + export function createLiteral(value: number): NumericLiteral; + export function createLiteral(value: boolean): BooleanLiteral; + /** Create a string literal whose source text is read from a source node during emit. */ + export function createLiteral(sourceNode: StringLiteral | NumericLiteral | Identifier): StringLiteral; + export function createLiteral(value: string | number | boolean): PrimaryExpression; + export function createLiteral(value: string | number | boolean | StringLiteral | NumericLiteral | Identifier): PrimaryExpression { if (typeof value === "number") { - const node = createNode(SyntaxKind.NumericLiteral, location, /*flags*/ undefined); - node.text = value.toString(); - return node; + return createNumericLiteral(value + ""); } - else if (typeof value === "boolean") { - return createNode(value ? SyntaxKind.TrueKeyword : SyntaxKind.FalseKeyword, location, /*flags*/ undefined); + if (typeof value === "boolean") { + return value ? createTrue() : createFalse(); } - else if (typeof value === "string") { - const node = createNode(SyntaxKind.StringLiteral, location, /*flags*/ undefined); - node.text = value; - return node; - } - else if (value) { - const node = createNode(SyntaxKind.StringLiteral, location, /*flags*/ undefined); - node.textSourceNode = value; - node.text = value.text; - return node; + if (typeof value === "string") { + return createStringLiteral(value); } + return createLiteralFromNode(value); } + export function createNumericLiteral(value: string): NumericLiteral { + const node = createSynthesizedNode(SyntaxKind.NumericLiteral); + node.text = value; + return node; + } + + function createStringLiteral(text: string): StringLiteral { + const node = createSynthesizedNode(SyntaxKind.StringLiteral); + node.text = text; + return node; + } + + function createLiteralFromNode(sourceNode: StringLiteral | NumericLiteral | Identifier): StringLiteral { + const node = createStringLiteral(sourceNode.text); + node.textSourceNode = sourceNode; + return node; + } + + // Identifiers - let nextAutoGenerateId = 0; - - export function createIdentifier(text: string, location?: TextRange): Identifier { - const node = createNode(SyntaxKind.Identifier, location); - node.text = escapeIdentifier(text); - node.originalKeywordKind = stringToToken(text); + export function createIdentifier(text: string): Identifier { + const node = createSynthesizedNode(SyntaxKind.Identifier); + node.text = text ? escapeIdentifier(text) : undefined; + node.originalKeywordKind = text ? stringToToken(text) : SyntaxKind.Unknown; node.autoGenerateKind = GeneratedIdentifierKind.None; node.autoGenerateId = 0; return node; } - export function createTempVariable(recordTempVariable: ((node: Identifier) => void) | undefined, location?: TextRange): Identifier { - const name = createNode(SyntaxKind.Identifier, location); - name.text = ""; - name.originalKeywordKind = SyntaxKind.Unknown; + let nextAutoGenerateId = 0; + + /** Create a unique temporary variable. */ + export function createTempVariable(recordTempVariable: ((node: Identifier) => void) | undefined): Identifier { + const name = createIdentifier(""); name.autoGenerateKind = GeneratedIdentifierKind.Auto; name.autoGenerateId = nextAutoGenerateId; nextAutoGenerateId++; @@ -155,33 +129,31 @@ namespace ts { return name; } - export function createLoopVariable(location?: TextRange): Identifier { - const name = createNode(SyntaxKind.Identifier, location); - name.text = ""; - name.originalKeywordKind = SyntaxKind.Unknown; + /** Create a unique temporary variable for use in a loop. */ + export function createLoopVariable(): Identifier { + const name = createIdentifier(""); name.autoGenerateKind = GeneratedIdentifierKind.Loop; name.autoGenerateId = nextAutoGenerateId; nextAutoGenerateId++; return name; } - export function createUniqueName(text: string, location?: TextRange): Identifier { - const name = createNode(SyntaxKind.Identifier, location); + /** Create a unique name based on the supplied text. */ + export function createUniqueName(text: string): Identifier { + const name = createIdentifier(""); name.text = text; - name.originalKeywordKind = SyntaxKind.Unknown; name.autoGenerateKind = GeneratedIdentifierKind.Unique; name.autoGenerateId = nextAutoGenerateId; nextAutoGenerateId++; return name; } - export function getGeneratedNameForNode(node: Node, location?: TextRange): Identifier { - const name = createNode(SyntaxKind.Identifier, location); - name.original = node; - name.text = ""; - name.originalKeywordKind = SyntaxKind.Unknown; + /** Create a unique name generated for a node. */ + export function getGeneratedNameForNode(node: Node): Identifier { + const name = createIdentifier(""); name.autoGenerateKind = GeneratedIdentifierKind.Node; name.autoGenerateId = nextAutoGenerateId; + name.original = node; nextAutoGenerateId++; return name; } @@ -189,49 +161,53 @@ namespace ts { // Punctuation export function createToken(token: TKind) { - return >createNode(token); + return >createSynthesizedNode(token); } // Reserved words export function createSuper() { - const node = createNode(SyntaxKind.SuperKeyword); - return node; + return createSynthesizedNode(SyntaxKind.SuperKeyword); } - export function createThis(location?: TextRange) { - const node = createNode(SyntaxKind.ThisKeyword, location); - return node; + export function createThis() { + return createSynthesizedNode(SyntaxKind.ThisKeyword); } export function createNull() { - const node = createNode(SyntaxKind.NullKeyword); - return node; + return createSynthesizedNode(SyntaxKind.NullKeyword); + } + + export function createTrue() { + return createSynthesizedNode(SyntaxKind.TrueKeyword); + } + + export function createFalse() { + return createSynthesizedNode(SyntaxKind.FalseKeyword); } // Names - export function createComputedPropertyName(expression: Expression, location?: TextRange) { - const node = createNode(SyntaxKind.ComputedPropertyName, location); + export function createComputedPropertyName(expression: Expression) { + const node = createSynthesizedNode(SyntaxKind.ComputedPropertyName); node.expression = expression; return node; } export function updateComputedPropertyName(node: ComputedPropertyName, expression: Expression) { - if (node.expression !== expression) { - return updateNode(createComputedPropertyName(expression, node), node); - } - return node; + return node.expression !== expression + ? updateNode(createComputedPropertyName(expression), node) + : node; } // Signature elements - export function createParameter(decorators: Decorator[], modifiers: Modifier[], dotDotDotToken: DotDotDotToken, name: string | Identifier | BindingPattern, questionToken?: QuestionToken, type?: TypeNode, initializer?: Expression, location?: TextRange, flags?: NodeFlags) { - const node = createNode(SyntaxKind.Parameter, location, flags); - node.decorators = decorators ? createNodeArray(decorators) : undefined; - node.modifiers = modifiers ? createNodeArray(modifiers) : undefined; + export function createParameter(decorators: Decorator[], modifiers: Modifier[], dotDotDotToken: DotDotDotToken, name: string | Identifier | BindingPattern, questionToken?: QuestionToken, type?: TypeNode, initializer?: Expression) { + const node = createSynthesizedNode(SyntaxKind.Parameter); + node.decorators = asNodeArray(decorators); + node.modifiers = asNodeArray(modifiers); node.dotDotDotToken = dotDotDotToken; - node.name = typeof name === "string" ? createIdentifier(name) : name; + node.name = asName(name); node.questionToken = questionToken; node.type = type; node.initializer = initializer ? parenthesizeExpressionForList(initializer) : undefined; @@ -239,20 +215,35 @@ namespace ts { } export function updateParameter(node: ParameterDeclaration, decorators: Decorator[], modifiers: Modifier[], dotDotDotToken: DotDotDotToken, name: BindingName, type: TypeNode, initializer: Expression) { - if (node.decorators !== decorators || node.modifiers !== modifiers || node.dotDotDotToken !== dotDotDotToken || node.name !== name || node.type !== type || node.initializer !== initializer) { - return updateNode(createParameter(decorators, modifiers, dotDotDotToken, name, node.questionToken, type, initializer, /*location*/ node, /*flags*/ node.flags), node); - } + return node.decorators !== decorators + || node.modifiers !== modifiers + || node.dotDotDotToken !== dotDotDotToken + || node.name !== name + || node.type !== type + || node.initializer !== initializer + ? updateNode(createParameter(decorators, modifiers, dotDotDotToken, name, node.questionToken, type, initializer), node) + : node; + } + export function createDecorator(expression: Expression) { + const node = createSynthesizedNode(SyntaxKind.Decorator); + node.expression = parenthesizeForAccess(expression); return node; } + export function updateDecorator(node: Decorator, expression: Expression) { + return node.expression !== expression + ? updateNode(createDecorator(expression), node) + : node; + } + // Type members - export function createProperty(decorators: Decorator[], modifiers: Modifier[], name: string | PropertyName, questionToken: QuestionToken, type: TypeNode, initializer: Expression, location?: TextRange) { - const node = createNode(SyntaxKind.PropertyDeclaration, location); - node.decorators = decorators ? createNodeArray(decorators) : undefined; - node.modifiers = modifiers ? createNodeArray(modifiers) : undefined; - node.name = typeof name === "string" ? createIdentifier(name) : name; + export function createProperty(decorators: Decorator[], modifiers: Modifier[], name: string | PropertyName, questionToken: QuestionToken, type: TypeNode, initializer: Expression) { + const node = createSynthesizedNode(SyntaxKind.PropertyDeclaration); + node.decorators = asNodeArray(decorators); + node.modifiers = asNodeArray(modifiers); + node.name = asName(name); node.questionToken = questionToken; node.type = type; node.initializer = initializer; @@ -260,19 +251,22 @@ namespace ts { } export function updateProperty(node: PropertyDeclaration, decorators: Decorator[], modifiers: Modifier[], name: PropertyName, type: TypeNode, initializer: Expression) { - if (node.decorators !== decorators || node.modifiers !== modifiers || node.name !== name || node.type !== type || node.initializer !== initializer) { - return updateNode(createProperty(decorators, modifiers, name, node.questionToken, type, initializer, node), node); - } - return node; + return node.decorators !== decorators + || node.modifiers !== modifiers + || node.name !== name + || node.type !== type + || node.initializer !== initializer + ? updateNode(createProperty(decorators, modifiers, name, node.questionToken, type, initializer), node) + : node; } - export function createMethod(decorators: Decorator[], modifiers: Modifier[], asteriskToken: AsteriskToken, name: string | PropertyName, typeParameters: TypeParameterDeclaration[], parameters: ParameterDeclaration[], type: TypeNode, body: Block, location?: TextRange, flags?: NodeFlags) { - const node = createNode(SyntaxKind.MethodDeclaration, location, flags); - node.decorators = decorators ? createNodeArray(decorators) : undefined; - node.modifiers = modifiers ? createNodeArray(modifiers) : undefined; + export function createMethod(decorators: Decorator[], modifiers: Modifier[], asteriskToken: AsteriskToken, name: string | PropertyName, typeParameters: TypeParameterDeclaration[], parameters: ParameterDeclaration[], type: TypeNode, body: Block) { + const node = createSynthesizedNode(SyntaxKind.MethodDeclaration); + node.decorators = asNodeArray(decorators); + node.modifiers = asNodeArray(modifiers); node.asteriskToken = asteriskToken; - node.name = typeof name === "string" ? createIdentifier(name) : name; - node.typeParameters = typeParameters ? createNodeArray(typeParameters) : undefined; + node.name = asName(name); + node.typeParameters = asNodeArray(typeParameters); node.parameters = createNodeArray(parameters); node.type = type; node.body = body; @@ -280,16 +274,21 @@ namespace ts { } export function updateMethod(node: MethodDeclaration, decorators: Decorator[], modifiers: Modifier[], name: PropertyName, typeParameters: TypeParameterDeclaration[], parameters: ParameterDeclaration[], type: TypeNode, body: Block) { - if (node.decorators !== decorators || node.modifiers !== modifiers || node.name !== name || node.typeParameters !== typeParameters || node.parameters !== parameters || node.type !== type || node.body !== body) { - return updateNode(createMethod(decorators, modifiers, node.asteriskToken, name, typeParameters, parameters, type, body, /*location*/ node, node.flags), node); - } - return node; + return node.decorators !== decorators + || node.modifiers !== modifiers + || node.name !== name + || node.typeParameters !== typeParameters + || node.parameters !== parameters + || node.type !== type + || node.body !== body + ? updateNode(createMethod(decorators, modifiers, node.asteriskToken, name, typeParameters, parameters, type, body), node) + : node; } - export function createConstructor(decorators: Decorator[], modifiers: Modifier[], parameters: ParameterDeclaration[], body: Block, location?: TextRange, flags?: NodeFlags) { - const node = createNode(SyntaxKind.Constructor, location, flags); - node.decorators = decorators ? createNodeArray(decorators) : undefined; - node.modifiers = modifiers ? createNodeArray(modifiers) : undefined; + export function createConstructor(decorators: Decorator[], modifiers: Modifier[], parameters: ParameterDeclaration[], body: Block) { + const node = createSynthesizedNode(SyntaxKind.Constructor); + node.decorators = asNodeArray(decorators); + node.modifiers = asNodeArray(modifiers); node.typeParameters = undefined; node.parameters = createNodeArray(parameters); node.type = undefined; @@ -298,17 +297,19 @@ namespace ts { } export function updateConstructor(node: ConstructorDeclaration, decorators: Decorator[], modifiers: Modifier[], parameters: ParameterDeclaration[], body: Block) { - if (node.decorators !== decorators || node.modifiers !== modifiers || node.parameters !== parameters || node.body !== body) { - return updateNode(createConstructor(decorators, modifiers, parameters, body, /*location*/ node, node.flags), node); - } - return node; + return node.decorators !== decorators + || node.modifiers !== modifiers + || node.parameters !== parameters + || node.body !== body + ? updateNode(createConstructor(decorators, modifiers, parameters, body), node) + : node; } - export function createGetAccessor(decorators: Decorator[], modifiers: Modifier[], name: string | PropertyName, parameters: ParameterDeclaration[], type: TypeNode, body: Block, location?: TextRange, flags?: NodeFlags) { - const node = createNode(SyntaxKind.GetAccessor, location, flags); - node.decorators = decorators ? createNodeArray(decorators) : undefined; - node.modifiers = modifiers ? createNodeArray(modifiers) : undefined; - node.name = typeof name === "string" ? createIdentifier(name) : name; + export function createGetAccessor(decorators: Decorator[], modifiers: Modifier[], name: string | PropertyName, parameters: ParameterDeclaration[], type: TypeNode, body: Block) { + const node = createSynthesizedNode(SyntaxKind.GetAccessor); + node.decorators = asNodeArray(decorators); + node.modifiers = asNodeArray(modifiers); + node.name = asName(name); node.typeParameters = undefined; node.parameters = createNodeArray(parameters); node.type = type; @@ -317,17 +318,21 @@ namespace ts { } export function updateGetAccessor(node: GetAccessorDeclaration, decorators: Decorator[], modifiers: Modifier[], name: PropertyName, parameters: ParameterDeclaration[], type: TypeNode, body: Block) { - if (node.decorators !== decorators || node.modifiers !== modifiers || node.name !== name || node.parameters !== parameters || node.type !== type || node.body !== body) { - return updateNode(createGetAccessor(decorators, modifiers, name, parameters, type, body, /*location*/ node, node.flags), node); - } - return node; + return node.decorators !== decorators + || node.modifiers !== modifiers + || node.name !== name + || node.parameters !== parameters + || node.type !== type + || node.body !== body + ? updateNode(createGetAccessor(decorators, modifiers, name, parameters, type, body), node) + : node; } - export function createSetAccessor(decorators: Decorator[], modifiers: Modifier[], name: string | PropertyName, parameters: ParameterDeclaration[], body: Block, location?: TextRange, flags?: NodeFlags) { - const node = createNode(SyntaxKind.SetAccessor, location, flags); - node.decorators = decorators ? createNodeArray(decorators) : undefined; - node.modifiers = modifiers ? createNodeArray(modifiers) : undefined; - node.name = typeof name === "string" ? createIdentifier(name) : name; + export function createSetAccessor(decorators: Decorator[], modifiers: Modifier[], name: string | PropertyName, parameters: ParameterDeclaration[], body: Block) { + const node = createSynthesizedNode(SyntaxKind.SetAccessor); + node.decorators = asNodeArray(decorators); + node.modifiers = asNodeArray(modifiers); + node.name = asName(name); node.typeParameters = undefined; node.parameters = createNodeArray(parameters); node.body = body; @@ -335,60 +340,63 @@ namespace ts { } export function updateSetAccessor(node: SetAccessorDeclaration, decorators: Decorator[], modifiers: Modifier[], name: PropertyName, parameters: ParameterDeclaration[], body: Block) { - if (node.decorators !== decorators || node.modifiers !== modifiers || node.name !== name || node.parameters !== parameters || node.body !== body) { - return updateNode(createSetAccessor(decorators, modifiers, name, parameters, body, /*location*/ node, node.flags), node); - } - return node; + return node.decorators !== decorators + || node.modifiers !== modifiers + || node.name !== name + || node.parameters !== parameters + || node.body !== body + ? updateNode(createSetAccessor(decorators, modifiers, name, parameters, body), node) + : node; } // Binding Patterns - export function createObjectBindingPattern(elements: BindingElement[], location?: TextRange) { - const node = createNode(SyntaxKind.ObjectBindingPattern, location); + export function createObjectBindingPattern(elements: BindingElement[]) { + const node = createSynthesizedNode(SyntaxKind.ObjectBindingPattern); node.elements = createNodeArray(elements); return node; } export function updateObjectBindingPattern(node: ObjectBindingPattern, elements: BindingElement[]) { - if (node.elements !== elements) { - return updateNode(createObjectBindingPattern(elements, node), node); - } - return node; + return node.elements !== elements + ? updateNode(createObjectBindingPattern(elements), node) + : node; } - export function createArrayBindingPattern(elements: ArrayBindingElement[], location?: TextRange) { - const node = createNode(SyntaxKind.ArrayBindingPattern, location); + export function createArrayBindingPattern(elements: ArrayBindingElement[]) { + const node = createSynthesizedNode(SyntaxKind.ArrayBindingPattern); node.elements = createNodeArray(elements); return node; } export function updateArrayBindingPattern(node: ArrayBindingPattern, elements: ArrayBindingElement[]) { - if (node.elements !== elements) { - return updateNode(createArrayBindingPattern(elements, node), node); - } - return node; + return node.elements !== elements + ? updateNode(createArrayBindingPattern(elements), node) + : node; } - export function createBindingElement(propertyName: string | PropertyName, dotDotDotToken: DotDotDotToken, name: string | BindingName, initializer?: Expression, location?: TextRange) { - const node = createNode(SyntaxKind.BindingElement, location); - node.propertyName = typeof propertyName === "string" ? createIdentifier(propertyName) : propertyName; + export function createBindingElement(propertyName: string | PropertyName, dotDotDotToken: DotDotDotToken, name: string | BindingName, initializer?: Expression) { + const node = createSynthesizedNode(SyntaxKind.BindingElement); + node.propertyName = asName(propertyName); node.dotDotDotToken = dotDotDotToken; - node.name = typeof name === "string" ? createIdentifier(name) : name; + node.name = asName(name); node.initializer = initializer; return node; } export function updateBindingElement(node: BindingElement, dotDotDotToken: DotDotDotToken, propertyName: PropertyName, name: BindingName, initializer: Expression) { - if (node.propertyName !== propertyName || node.dotDotDotToken !== dotDotDotToken || node.name !== name || node.initializer !== initializer) { - return updateNode(createBindingElement(propertyName, dotDotDotToken, name, initializer, node), node); - } - return node; + return node.propertyName !== propertyName + || node.dotDotDotToken !== dotDotDotToken + || node.name !== name + || node.initializer !== initializer + ? updateNode(createBindingElement(propertyName, dotDotDotToken, name, initializer), node) + : node; } // Expression - export function createArrayLiteral(elements?: Expression[], location?: TextRange, multiLine?: boolean) { - const node = createNode(SyntaxKind.ArrayLiteralExpression, location); + export function createArrayLiteral(elements?: Expression[], multiLine?: boolean) { + const node = createSynthesizedNode(SyntaxKind.ArrayLiteralExpression); node.elements = parenthesizeListElements(createNodeArray(elements)); if (multiLine) { node.multiLine = true; @@ -398,14 +406,13 @@ namespace ts { } export function updateArrayLiteral(node: ArrayLiteralExpression, elements: Expression[]) { - if (node.elements !== elements) { - return updateNode(createArrayLiteral(elements, node, node.multiLine), node); - } - return node; + return node.elements !== elements + ? updateNode(createArrayLiteral(elements, node.multiLine), node) + : node; } - export function createObjectLiteral(properties?: ObjectLiteralElementLike[], location?: TextRange, multiLine?: boolean) { - const node = createNode(SyntaxKind.ObjectLiteralExpression, location); + export function createObjectLiteral(properties?: ObjectLiteralElementLike[], multiLine?: boolean) { + const node = createSynthesizedNode(SyntaxKind.ObjectLiteralExpression); node.properties = createNodeArray(properties); if (multiLine) { node.multiLine = true; @@ -414,110 +421,106 @@ namespace ts { } export function updateObjectLiteral(node: ObjectLiteralExpression, properties: ObjectLiteralElementLike[]) { - if (node.properties !== properties) { - return updateNode(createObjectLiteral(properties, node, node.multiLine), node); - } - return node; + return node.properties !== properties + ? updateNode(createObjectLiteral(properties, node.multiLine), node) + : node; } - export function createPropertyAccess(expression: Expression, name: string | Identifier, location?: TextRange, flags?: NodeFlags) { - const node = createNode(SyntaxKind.PropertyAccessExpression, location, flags); + export function createPropertyAccess(expression: Expression, name: string | Identifier) { + const node = createSynthesizedNode(SyntaxKind.PropertyAccessExpression); node.expression = parenthesizeForAccess(expression); - (node.emitNode || (node.emitNode = {})).flags |= EmitFlags.NoIndentation; - node.name = typeof name === "string" ? createIdentifier(name) : name; + node.name = asName(name); + setEmitFlags(node, EmitFlags.NoIndentation); return node; } export function updatePropertyAccess(node: PropertyAccessExpression, expression: Expression, name: Identifier) { - if (node.expression !== expression || node.name !== name) { - const propertyAccess = createPropertyAccess(expression, name, /*location*/ node, node.flags); - // Because we are updating existed propertyAccess we want to inherit its emitFlags instead of using default from createPropertyAccess - (propertyAccess.emitNode || (propertyAccess.emitNode = {})).flags = getEmitFlags(node); - return updateNode(propertyAccess, node); - } - return node; + // Because we are updating existed propertyAccess we want to inherit its emitFlags + // instead of using the default from createPropertyAccess + return node.expression !== expression + || node.name !== name + ? updateNode(setEmitFlags(createPropertyAccess(expression, name), getEmitFlags(node)), node) + : node; } - export function createElementAccess(expression: Expression, index: number | Expression, location?: TextRange) { - const node = createNode(SyntaxKind.ElementAccessExpression, location); + export function createElementAccess(expression: Expression, index: number | Expression) { + const node = createSynthesizedNode(SyntaxKind.ElementAccessExpression); node.expression = parenthesizeForAccess(expression); - node.argumentExpression = typeof index === "number" ? createLiteral(index) : index; + node.argumentExpression = asExpression(index); return node; } export function updateElementAccess(node: ElementAccessExpression, expression: Expression, argumentExpression: Expression) { - if (node.expression !== expression || node.argumentExpression !== argumentExpression) { - return updateNode(createElementAccess(expression, argumentExpression, node), node); - } - return node; + return node.expression !== expression + || node.argumentExpression !== argumentExpression + ? updateNode(createElementAccess(expression, argumentExpression), node) + : node; } - export function createCall(expression: Expression, typeArguments: TypeNode[], argumentsArray: Expression[], location?: TextRange, flags?: NodeFlags) { - const node = createNode(SyntaxKind.CallExpression, location, flags); + export function createCall(expression: Expression, typeArguments: TypeNode[], argumentsArray: Expression[]) { + const node = createSynthesizedNode(SyntaxKind.CallExpression); node.expression = parenthesizeForAccess(expression); - if (typeArguments) { - node.typeArguments = createNodeArray(typeArguments); - } - + node.typeArguments = asNodeArray(typeArguments); node.arguments = parenthesizeListElements(createNodeArray(argumentsArray)); return node; } export function updateCall(node: CallExpression, expression: Expression, typeArguments: TypeNode[], argumentsArray: Expression[]) { - if (expression !== node.expression || typeArguments !== node.typeArguments || argumentsArray !== node.arguments) { - return updateNode(createCall(expression, typeArguments, argumentsArray, /*location*/ node, node.flags), node); - } - return node; + return expression !== node.expression + || typeArguments !== node.typeArguments + || argumentsArray !== node.arguments + ? updateNode(createCall(expression, typeArguments, argumentsArray), node) + : node; } - export function createNew(expression: Expression, typeArguments: TypeNode[], argumentsArray: Expression[], location?: TextRange, flags?: NodeFlags) { - const node = createNode(SyntaxKind.NewExpression, location, flags); + export function createNew(expression: Expression, typeArguments: TypeNode[], argumentsArray: Expression[]) { + const node = createSynthesizedNode(SyntaxKind.NewExpression); node.expression = parenthesizeForNew(expression); - node.typeArguments = typeArguments ? createNodeArray(typeArguments) : undefined; + node.typeArguments = asNodeArray(typeArguments); node.arguments = argumentsArray ? parenthesizeListElements(createNodeArray(argumentsArray)) : undefined; return node; } export function updateNew(node: NewExpression, expression: Expression, typeArguments: TypeNode[], argumentsArray: Expression[]) { - if (node.expression !== expression || node.typeArguments !== typeArguments || node.arguments !== argumentsArray) { - return updateNode(createNew(expression, typeArguments, argumentsArray, /*location*/ node, node.flags), node); - } - return node; + return node.expression !== expression + || node.typeArguments !== typeArguments + || node.arguments !== argumentsArray + ? updateNode(createNew(expression, typeArguments, argumentsArray), node) + : node; } - export function createTaggedTemplate(tag: Expression, template: TemplateLiteral, location?: TextRange) { - const node = createNode(SyntaxKind.TaggedTemplateExpression, location); + export function createTaggedTemplate(tag: Expression, template: TemplateLiteral) { + const node = createSynthesizedNode(SyntaxKind.TaggedTemplateExpression); node.tag = parenthesizeForAccess(tag); node.template = template; return node; } export function updateTaggedTemplate(node: TaggedTemplateExpression, tag: Expression, template: TemplateLiteral) { - if (node.tag !== tag || node.template !== template) { - return updateNode(createTaggedTemplate(tag, template, node), node); - } - return node; + return node.tag !== tag + || node.template !== template + ? updateNode(createTaggedTemplate(tag, template), node) + : node; } - export function createParen(expression: Expression, location?: TextRange) { - const node = createNode(SyntaxKind.ParenthesizedExpression, location); + export function createParen(expression: Expression) { + const node = createSynthesizedNode(SyntaxKind.ParenthesizedExpression); node.expression = expression; return node; } export function updateParen(node: ParenthesizedExpression, expression: Expression) { - if (node.expression !== expression) { - return updateNode(createParen(expression, node), node); - } - return node; + return node.expression !== expression + ? updateNode(createParen(expression), node) + : node; } - export function createFunctionExpression(modifiers: Modifier[], asteriskToken: AsteriskToken, name: string | Identifier, typeParameters: TypeParameterDeclaration[], parameters: ParameterDeclaration[], type: TypeNode, body: Block, location?: TextRange, flags?: NodeFlags) { - const node = createNode(SyntaxKind.FunctionExpression, location, flags); - node.modifiers = modifiers ? createNodeArray(modifiers) : undefined; + export function createFunctionExpression(modifiers: Modifier[], asteriskToken: AsteriskToken, name: string | Identifier, typeParameters: TypeParameterDeclaration[], parameters: ParameterDeclaration[], type: TypeNode, body: Block) { + const node = createSynthesizedNode(SyntaxKind.FunctionExpression); + node.modifiers = asNodeArray(modifiers); node.asteriskToken = asteriskToken; - node.name = typeof name === "string" ? createIdentifier(name) : name; - node.typeParameters = typeParameters ? createNodeArray(typeParameters) : undefined; + node.name = asName(name); + node.typeParameters = asNodeArray(typeParameters); node.parameters = createNodeArray(parameters); node.type = type; node.body = body; @@ -525,16 +528,20 @@ namespace ts { } export function updateFunctionExpression(node: FunctionExpression, modifiers: Modifier[], name: Identifier, typeParameters: TypeParameterDeclaration[], parameters: ParameterDeclaration[], type: TypeNode, body: Block) { - if (node.name !== name || node.modifiers !== modifiers || node.typeParameters !== typeParameters || node.parameters !== parameters || node.type !== type || node.body !== body) { - return updateNode(createFunctionExpression(modifiers, node.asteriskToken, name, typeParameters, parameters, type, body, /*location*/ node, node.flags), node); - } - return node; + return node.name !== name + || node.modifiers !== modifiers + || node.typeParameters !== typeParameters + || node.parameters !== parameters + || node.type !== type + || node.body !== body + ? updateNode(createFunctionExpression(modifiers, node.asteriskToken, name, typeParameters, parameters, type, body), node) + : node; } - export function createArrowFunction(modifiers: Modifier[], typeParameters: TypeParameterDeclaration[], parameters: ParameterDeclaration[], type: TypeNode, equalsGreaterThanToken: EqualsGreaterThanToken, body: ConciseBody, location?: TextRange, flags?: NodeFlags) { - const node = createNode(SyntaxKind.ArrowFunction, location, flags); - node.modifiers = modifiers ? createNodeArray(modifiers) : undefined; - node.typeParameters = typeParameters ? createNodeArray(typeParameters) : undefined; + export function createArrowFunction(modifiers: Modifier[], typeParameters: TypeParameterDeclaration[], parameters: ParameterDeclaration[], type: TypeNode, equalsGreaterThanToken: EqualsGreaterThanToken, body: ConciseBody) { + const node = createSynthesizedNode(SyntaxKind.ArrowFunction); + node.modifiers = asNodeArray(modifiers); + node.typeParameters = asNodeArray(typeParameters); node.parameters = createNodeArray(parameters); node.type = type; node.equalsGreaterThanToken = equalsGreaterThanToken || createToken(SyntaxKind.EqualsGreaterThanToken); @@ -543,96 +550,93 @@ namespace ts { } export function updateArrowFunction(node: ArrowFunction, modifiers: Modifier[], typeParameters: TypeParameterDeclaration[], parameters: ParameterDeclaration[], type: TypeNode, body: ConciseBody) { - if (node.modifiers !== modifiers || node.typeParameters !== typeParameters || node.parameters !== parameters || node.type !== type || node.body !== body) { - return updateNode(createArrowFunction(modifiers, typeParameters, parameters, type, node.equalsGreaterThanToken, body, /*location*/ node, node.flags), node); - } - return node; + return node.modifiers !== modifiers + || node.typeParameters !== typeParameters + || node.parameters !== parameters + || node.type !== type + || node.body !== body + ? updateNode(createArrowFunction(modifiers, typeParameters, parameters, type, node.equalsGreaterThanToken, body), node) + : node; } - export function createDelete(expression: Expression, location?: TextRange) { - const node = createNode(SyntaxKind.DeleteExpression, location); + export function createDelete(expression: Expression) { + const node = createSynthesizedNode(SyntaxKind.DeleteExpression); node.expression = parenthesizePrefixOperand(expression); return node; } export function updateDelete(node: DeleteExpression, expression: Expression) { - if (node.expression !== expression) { - return updateNode(createDelete(expression, node), expression); - } - return node; + return node.expression !== expression + ? updateNode(createDelete(expression), node) + : node; } - export function createTypeOf(expression: Expression, location?: TextRange) { - const node = createNode(SyntaxKind.TypeOfExpression, location); + export function createTypeOf(expression: Expression) { + const node = createSynthesizedNode(SyntaxKind.TypeOfExpression); node.expression = parenthesizePrefixOperand(expression); return node; } export function updateTypeOf(node: TypeOfExpression, expression: Expression) { - if (node.expression !== expression) { - return updateNode(createTypeOf(expression, node), expression); - } - return node; + return node.expression !== expression + ? updateNode(createTypeOf(expression), node) + : node; } - export function createVoid(expression: Expression, location?: TextRange) { - const node = createNode(SyntaxKind.VoidExpression, location); + export function createVoid(expression: Expression) { + const node = createSynthesizedNode(SyntaxKind.VoidExpression); node.expression = parenthesizePrefixOperand(expression); return node; } export function updateVoid(node: VoidExpression, expression: Expression) { - if (node.expression !== expression) { - return updateNode(createVoid(expression, node), node); - } - return node; + return node.expression !== expression + ? updateNode(createVoid(expression), node) + : node; } - export function createAwait(expression: Expression, location?: TextRange) { - const node = createNode(SyntaxKind.AwaitExpression, location); + export function createAwait(expression: Expression) { + const node = createSynthesizedNode(SyntaxKind.AwaitExpression); node.expression = parenthesizePrefixOperand(expression); return node; } export function updateAwait(node: AwaitExpression, expression: Expression) { - if (node.expression !== expression) { - return updateNode(createAwait(expression, node), node); - } - return node; + return node.expression !== expression + ? updateNode(createAwait(expression), node) + : node; } - export function createPrefix(operator: PrefixUnaryOperator, operand: Expression, location?: TextRange) { - const node = createNode(SyntaxKind.PrefixUnaryExpression, location); + export function createPrefix(operator: PrefixUnaryOperator, operand: Expression) { + const node = createSynthesizedNode(SyntaxKind.PrefixUnaryExpression); node.operator = operator; node.operand = parenthesizePrefixOperand(operand); return node; } export function updatePrefix(node: PrefixUnaryExpression, operand: Expression) { - if (node.operand !== operand) { - return updateNode(createPrefix(node.operator, operand, node), node); - } - return node; + return node.operand !== operand + ? updateNode(createPrefix(node.operator, operand), node) + : node; } - export function createPostfix(operand: Expression, operator: PostfixUnaryOperator, location?: TextRange) { - const node = createNode(SyntaxKind.PostfixUnaryExpression, location); + export function createPostfix(operand: Expression, operator: PostfixUnaryOperator) { + const node = createSynthesizedNode(SyntaxKind.PostfixUnaryExpression); node.operand = parenthesizePostfixOperand(operand); node.operator = operator; return node; } export function updatePostfix(node: PostfixUnaryExpression, operand: Expression) { - if (node.operand !== operand) { - return updateNode(createPostfix(operand, node.operator, node), node); - } - return node; + return node.operand !== operand + ? updateNode(createPostfix(operand, node.operator), node) + : node; } - export function createBinary(left: Expression, operator: BinaryOperator | BinaryOperatorToken, right: Expression, location?: TextRange) { - const operatorToken = typeof operator === "number" ? createToken(operator) : operator; + export function createBinary(left: Expression, operator: BinaryOperator | BinaryOperatorToken, right: Expression) { + const node = createSynthesizedNode(SyntaxKind.BinaryExpression); + const operatorToken = asToken(operator); const operatorKind = operatorToken.kind; - const node = createNode(SyntaxKind.BinaryExpression, location); node.left = parenthesizeBinaryOperand(operatorKind, left, /*isLeftSideOfBinary*/ true, /*leftOperand*/ undefined); node.operatorToken = operatorToken; node.right = parenthesizeBinaryOperand(operatorKind, right, /*isLeftSideOfBinary*/ false, node.left); @@ -640,218 +644,205 @@ namespace ts { } export function updateBinary(node: BinaryExpression, left: Expression, right: Expression) { - if (node.left !== left || node.right !== right) { - return updateNode(createBinary(left, node.operatorToken, right, /*location*/ node), node); - } - return node; + return node.left !== left + || node.right !== right + ? updateNode(createBinary(left, node.operatorToken, right), node) + : node; } - export function createConditional(condition: Expression, whenTrue: Expression, whenFalse: Expression, location?: TextRange): ConditionalExpression; - export function createConditional(condition: Expression, questionToken: QuestionToken, whenTrue: Expression, colonToken: ColonToken, whenFalse: Expression, location?: TextRange): ConditionalExpression; - export function createConditional(condition: Expression, questionTokenOrWhenTrue: QuestionToken | Expression, whenTrueOrWhenFalse: Expression, colonTokenOrLocation?: ColonToken | TextRange, whenFalse?: Expression, location?: TextRange) { - const node = createNode(SyntaxKind.ConditionalExpression, whenFalse ? location : colonTokenOrLocation); + export function createConditional(condition: Expression, whenTrue: Expression, whenFalse: Expression): ConditionalExpression; + export function createConditional(condition: Expression, questionToken: QuestionToken, whenTrue: Expression, colonToken: ColonToken, whenFalse: Expression): ConditionalExpression; + export function createConditional(condition: Expression, questionTokenOrWhenTrue: QuestionToken | Expression, whenTrueOrWhenFalse: Expression, colonToken?: ColonToken, whenFalse?: Expression) { + const node = createSynthesizedNode(SyntaxKind.ConditionalExpression); node.condition = parenthesizeForConditionalHead(condition); - if (whenFalse) { - // second overload - node.questionToken = questionTokenOrWhenTrue; - node.whenTrue = parenthesizeSubexpressionOfConditionalExpression(whenTrueOrWhenFalse); - node.colonToken = colonTokenOrLocation; - node.whenFalse = parenthesizeSubexpressionOfConditionalExpression(whenFalse); - } - else { - // first overload - node.questionToken = createToken(SyntaxKind.QuestionToken); - node.whenTrue = parenthesizeSubexpressionOfConditionalExpression(questionTokenOrWhenTrue); - node.colonToken = createToken(SyntaxKind.ColonToken); - node.whenFalse = parenthesizeSubexpressionOfConditionalExpression(whenTrueOrWhenFalse); - } + node.questionToken = whenFalse ? questionTokenOrWhenTrue : createToken(SyntaxKind.QuestionToken); + node.whenTrue = parenthesizeSubexpressionOfConditionalExpression(whenFalse ? whenTrueOrWhenFalse : questionTokenOrWhenTrue); + node.colonToken = whenFalse ? colonToken : createToken(SyntaxKind.ColonToken); + node.whenFalse = parenthesizeSubexpressionOfConditionalExpression(whenFalse ? whenFalse : whenTrueOrWhenFalse); return node; } export function updateConditional(node: ConditionalExpression, condition: Expression, whenTrue: Expression, whenFalse: Expression) { - if (node.condition !== condition || node.whenTrue !== whenTrue || node.whenFalse !== whenFalse) { - return updateNode(createConditional(condition, node.questionToken, whenTrue, node.colonToken, whenFalse, node), node); - } - return node; + return node.condition !== condition + || node.whenTrue !== whenTrue + || node.whenFalse !== whenFalse + ? updateNode(createConditional(condition, node.questionToken, whenTrue, node.colonToken, whenFalse), node) + : node; } - export function createTemplateExpression(head: TemplateHead, templateSpans: TemplateSpan[], location?: TextRange) { - const node = createNode(SyntaxKind.TemplateExpression, location); + export function createTemplateExpression(head: TemplateHead, templateSpans: TemplateSpan[]) { + const node = createSynthesizedNode(SyntaxKind.TemplateExpression); node.head = head; node.templateSpans = createNodeArray(templateSpans); return node; } export function updateTemplateExpression(node: TemplateExpression, head: TemplateHead, templateSpans: TemplateSpan[]) { - if (node.head !== head || node.templateSpans !== templateSpans) { - return updateNode(createTemplateExpression(head, templateSpans, node), node); - } - return node; + return node.head !== head + || node.templateSpans !== templateSpans + ? updateNode(createTemplateExpression(head, templateSpans), node) + : node; } - export function createYield(asteriskToken: AsteriskToken, expression: Expression, location?: TextRange) { - const node = createNode(SyntaxKind.YieldExpression, location); - node.asteriskToken = asteriskToken; - node.expression = expression; + export function createYield(expression?: Expression): YieldExpression; + export function createYield(asteriskToken: AsteriskToken, expression: Expression): YieldExpression; + export function createYield(asteriskTokenOrExpression?: AsteriskToken | Expression, expression?: Expression) { + const node = createSynthesizedNode(SyntaxKind.YieldExpression); + node.asteriskToken = asteriskTokenOrExpression && asteriskTokenOrExpression.kind === SyntaxKind.AsteriskToken ? asteriskTokenOrExpression : undefined; + node.expression = asteriskTokenOrExpression && asteriskTokenOrExpression.kind !== SyntaxKind.AsteriskToken ? asteriskTokenOrExpression : expression; return node; } export function updateYield(node: YieldExpression, expression: Expression) { - if (node.expression !== expression) { - return updateNode(createYield(node.asteriskToken, expression, node), node); - } - return node; + return node.expression !== expression + ? updateNode(createYield(node.asteriskToken, expression), node) + : node; } - export function createSpread(expression: Expression, location?: TextRange) { - const node = createNode(SyntaxKind.SpreadElement, location); + export function createSpread(expression: Expression) { + const node = createSynthesizedNode(SyntaxKind.SpreadElement); node.expression = parenthesizeExpressionForList(expression); return node; } export function updateSpread(node: SpreadElement, expression: Expression) { - if (node.expression !== expression) { - return updateNode(createSpread(expression, node), node); - } - return node; + return node.expression !== expression + ? updateNode(createSpread(expression), node) + : node; } - export function createClassExpression(modifiers: Modifier[], name: Identifier, typeParameters: TypeParameterDeclaration[], heritageClauses: HeritageClause[], members: ClassElement[], location?: TextRange) { - const node = createNode(SyntaxKind.ClassExpression, location); + export function createClassExpression(modifiers: Modifier[], name: string | Identifier, typeParameters: TypeParameterDeclaration[], heritageClauses: HeritageClause[], members: ClassElement[]) { + const node = createSynthesizedNode(SyntaxKind.ClassExpression); node.decorators = undefined; - node.modifiers = modifiers ? createNodeArray(modifiers) : undefined; - node.name = name; - node.typeParameters = typeParameters ? createNodeArray(typeParameters) : undefined; - node.heritageClauses = createNodeArray(heritageClauses); + node.modifiers = asNodeArray(modifiers); + node.name = asName(name); + node.typeParameters = asNodeArray(typeParameters); + node.heritageClauses = asNodeArray(heritageClauses); node.members = createNodeArray(members); return node; } export function updateClassExpression(node: ClassExpression, modifiers: Modifier[], name: Identifier, typeParameters: TypeParameterDeclaration[], heritageClauses: HeritageClause[], members: ClassElement[]) { - if (node.modifiers !== modifiers || node.name !== name || node.typeParameters !== typeParameters || node.heritageClauses !== heritageClauses || node.members !== members) { - return updateNode(createClassExpression(modifiers, name, typeParameters, heritageClauses, members, node), node); - } - return node; + return node.modifiers !== modifiers + || node.name !== name + || node.typeParameters !== typeParameters + || node.heritageClauses !== heritageClauses + || node.members !== members + ? updateNode(createClassExpression(modifiers, name, typeParameters, heritageClauses, members), node) + : node; } - export function createOmittedExpression(location?: TextRange) { - const node = createNode(SyntaxKind.OmittedExpression, location); - return node; + export function createOmittedExpression() { + return createSynthesizedNode(SyntaxKind.OmittedExpression); } - export function createExpressionWithTypeArguments(typeArguments: TypeNode[], expression: Expression, location?: TextRange) { - const node = createNode(SyntaxKind.ExpressionWithTypeArguments, location); - node.typeArguments = typeArguments ? createNodeArray(typeArguments) : undefined; + export function createExpressionWithTypeArguments(typeArguments: TypeNode[], expression: Expression) { + const node = createSynthesizedNode(SyntaxKind.ExpressionWithTypeArguments); node.expression = parenthesizeForAccess(expression); + node.typeArguments = asNodeArray(typeArguments); return node; } export function updateExpressionWithTypeArguments(node: ExpressionWithTypeArguments, typeArguments: TypeNode[], expression: Expression) { - if (node.typeArguments !== typeArguments || node.expression !== expression) { - return updateNode(createExpressionWithTypeArguments(typeArguments, expression, node), node); - } - return node; + return node.typeArguments !== typeArguments + || node.expression !== expression + ? updateNode(createExpressionWithTypeArguments(typeArguments, expression), node) + : node; } - // Misc - export function createTemplateSpan(expression: Expression, literal: TemplateMiddle | TemplateTail, location?: TextRange) { - const node = createNode(SyntaxKind.TemplateSpan, location); + export function createTemplateSpan(expression: Expression, literal: TemplateMiddle | TemplateTail) { + const node = createSynthesizedNode(SyntaxKind.TemplateSpan); node.expression = expression; node.literal = literal; return node; } export function updateTemplateSpan(node: TemplateSpan, expression: Expression, literal: TemplateMiddle | TemplateTail) { - if (node.expression !== expression || node.literal !== literal) { - return updateNode(createTemplateSpan(expression, literal, node), node); - } - return node; + return node.expression !== expression + || node.literal !== literal + ? updateNode(createTemplateSpan(expression, literal), node) + : node; } // Element - export function createBlock(statements: Statement[], location?: TextRange, multiLine?: boolean, flags?: NodeFlags): Block { - const block = createNode(SyntaxKind.Block, location, flags); + export function createBlock(statements: Statement[], multiLine?: boolean): Block { + const block = createSynthesizedNode(SyntaxKind.Block); block.statements = createNodeArray(statements); - if (multiLine) { - block.multiLine = true; - } + if (multiLine) block.multiLine = multiLine; return block; } export function updateBlock(node: Block, statements: Statement[]) { - if (statements !== node.statements) { - return updateNode(createBlock(statements, /*location*/ node, node.multiLine, node.flags), node); - } - - return node; + return statements !== node.statements + ? updateNode(createBlock(statements, node.multiLine), node) + : node; } - export function createVariableStatement(modifiers: Modifier[], declarationList: VariableDeclarationList | VariableDeclaration[], location?: TextRange, flags?: NodeFlags): VariableStatement { - const node = createNode(SyntaxKind.VariableStatement, location, flags); + export function createVariableStatement(modifiers: Modifier[], declarationList: VariableDeclarationList | VariableDeclaration[]): VariableStatement { + const node = createSynthesizedNode(SyntaxKind.VariableStatement); node.decorators = undefined; - node.modifiers = modifiers ? createNodeArray(modifiers) : undefined; + node.modifiers = asNodeArray(modifiers); node.declarationList = isArray(declarationList) ? createVariableDeclarationList(declarationList) : declarationList; return node; } export function updateVariableStatement(node: VariableStatement, modifiers: Modifier[], declarationList: VariableDeclarationList): VariableStatement { - if (node.modifiers !== modifiers || node.declarationList !== declarationList) { - return updateNode(createVariableStatement(modifiers, declarationList, /*location*/ node, node.flags), node); - } - return node; + return node.modifiers !== modifiers + || node.declarationList !== declarationList + ? updateNode(createVariableStatement(modifiers, declarationList), node) + : node; } - export function createVariableDeclarationList(declarations: VariableDeclaration[], location?: TextRange, flags?: NodeFlags): VariableDeclarationList { - const node = createNode(SyntaxKind.VariableDeclarationList, location, flags); + export function createVariableDeclarationList(declarations: VariableDeclaration[], flags?: NodeFlags): VariableDeclarationList { + const node = createSynthesizedNode(SyntaxKind.VariableDeclarationList); + node.flags |= flags; node.declarations = createNodeArray(declarations); return node; } export function updateVariableDeclarationList(node: VariableDeclarationList, declarations: VariableDeclaration[]) { - if (node.declarations !== declarations) { - return updateNode(createVariableDeclarationList(declarations, /*location*/ node, node.flags), node); - } - return node; + return node.declarations !== declarations + ? updateNode(createVariableDeclarationList(declarations, node.flags), node) + : node; } - export function createVariableDeclaration(name: string | BindingPattern | Identifier, type?: TypeNode, initializer?: Expression, location?: TextRange, flags?: NodeFlags): VariableDeclaration { - const node = createNode(SyntaxKind.VariableDeclaration, location, flags); - node.name = typeof name === "string" ? createIdentifier(name) : name; + export function createVariableDeclaration(name: string | BindingName, type?: TypeNode, initializer?: Expression): VariableDeclaration { + const node = createSynthesizedNode(SyntaxKind.VariableDeclaration); + node.name = asName(name); node.type = type; node.initializer = initializer !== undefined ? parenthesizeExpressionForList(initializer) : undefined; return node; } export function updateVariableDeclaration(node: VariableDeclaration, name: BindingName, type: TypeNode, initializer: Expression) { - if (node.name !== name || node.type !== type || node.initializer !== initializer) { - return updateNode(createVariableDeclaration(name, type, initializer, /*location*/ node, node.flags), node); - } - return node; + return node.name !== name + || node.type !== type + || node.initializer !== initializer + ? updateNode(createVariableDeclaration(name, type, initializer), node) + : node; } - export function createEmptyStatement(location: TextRange) { - return createNode(SyntaxKind.EmptyStatement, location); + export function createEmptyStatement() { + return createSynthesizedNode(SyntaxKind.EmptyStatement); } - export function createStatement(expression: Expression, location?: TextRange, flags?: NodeFlags): ExpressionStatement { - const node = createNode(SyntaxKind.ExpressionStatement, location, flags); + export function createStatement(expression: Expression): ExpressionStatement { + const node = createSynthesizedNode(SyntaxKind.ExpressionStatement); node.expression = parenthesizeExpressionForExpressionStatement(expression); return node; } export function updateStatement(node: ExpressionStatement, expression: Expression) { - if (node.expression !== expression) { - return updateNode(createStatement(expression, /*location*/ node, node.flags), node); - } - - return node; + return node.expression !== expression + ? updateNode(createStatement(expression), node) + : node; } - export function createIf(expression: Expression, thenStatement: Statement, elseStatement?: Statement, location?: TextRange) { - const node = createNode(SyntaxKind.IfStatement, location); + export function createIf(expression: Expression, thenStatement: Statement, elseStatement?: Statement) { + const node = createSynthesizedNode(SyntaxKind.IfStatement); node.expression = expression; node.thenStatement = thenStatement; node.elseStatement = elseStatement; @@ -859,42 +850,43 @@ namespace ts { } export function updateIf(node: IfStatement, expression: Expression, thenStatement: Statement, elseStatement: Statement) { - if (node.expression !== expression || node.thenStatement !== thenStatement || node.elseStatement !== elseStatement) { - return updateNode(createIf(expression, thenStatement, elseStatement, /*location*/ node), node); - } - return node; + return node.expression !== expression + || node.thenStatement !== thenStatement + || node.elseStatement !== elseStatement + ? updateNode(createIf(expression, thenStatement, elseStatement), node) + : node; } - export function createDo(statement: Statement, expression: Expression, location?: TextRange) { - const node = createNode(SyntaxKind.DoStatement, location); + export function createDo(statement: Statement, expression: Expression) { + const node = createSynthesizedNode(SyntaxKind.DoStatement); node.statement = statement; node.expression = expression; return node; } export function updateDo(node: DoStatement, statement: Statement, expression: Expression) { - if (node.statement !== statement || node.expression !== expression) { - return updateNode(createDo(statement, expression, node), node); - } - return node; + return node.statement !== statement + || node.expression !== expression + ? updateNode(createDo(statement, expression), node) + : node; } - export function createWhile(expression: Expression, statement: Statement, location?: TextRange) { - const node = createNode(SyntaxKind.WhileStatement, location); + export function createWhile(expression: Expression, statement: Statement) { + const node = createSynthesizedNode(SyntaxKind.WhileStatement); node.expression = expression; node.statement = statement; return node; } export function updateWhile(node: WhileStatement, expression: Expression, statement: Statement) { - if (node.expression !== expression || node.statement !== statement) { - return updateNode(createWhile(expression, statement, node), node); - } - return node; + return node.expression !== expression + || node.statement !== statement + ? updateNode(createWhile(expression, statement), node) + : node; } - export function createFor(initializer: ForInitializer, condition: Expression, incrementor: Expression, statement: Statement, location?: TextRange) { - const node = createNode(SyntaxKind.ForStatement, location, /*flags*/ undefined); + export function createFor(initializer: ForInitializer, condition: Expression, incrementor: Expression, statement: Statement) { + const node = createSynthesizedNode(SyntaxKind.ForStatement); node.initializer = initializer; node.condition = condition; node.incrementor = incrementor; @@ -903,14 +895,16 @@ namespace ts { } export function updateFor(node: ForStatement, initializer: ForInitializer, condition: Expression, incrementor: Expression, statement: Statement) { - if (node.initializer !== initializer || node.condition !== condition || node.incrementor !== incrementor || node.statement !== statement) { - return updateNode(createFor(initializer, condition, incrementor, statement, node), node); - } - return node; + return node.initializer !== initializer + || node.condition !== condition + || node.incrementor !== incrementor + || node.statement !== statement + ? updateNode(createFor(initializer, condition, incrementor, statement), node) + : node; } - export function createForIn(initializer: ForInitializer, expression: Expression, statement: Statement, location?: TextRange) { - const node = createNode(SyntaxKind.ForInStatement, location); + export function createForIn(initializer: ForInitializer, expression: Expression, statement: Statement) { + const node = createSynthesizedNode(SyntaxKind.ForInStatement); node.initializer = initializer; node.expression = expression; node.statement = statement; @@ -918,14 +912,15 @@ namespace ts { } export function updateForIn(node: ForInStatement, initializer: ForInitializer, expression: Expression, statement: Statement) { - if (node.initializer !== initializer || node.expression !== expression || node.statement !== statement) { - return updateNode(createForIn(initializer, expression, statement, node), node); - } - return node; + return node.initializer !== initializer + || node.expression !== expression + || node.statement !== statement + ? updateNode(createForIn(initializer, expression, statement), node) + : node; } - export function createForOf(initializer: ForInitializer, expression: Expression, statement: Statement, location?: TextRange) { - const node = createNode(SyntaxKind.ForOfStatement, location); + export function createForOf(initializer: ForInitializer, expression: Expression, statement: Statement) { + const node = createSynthesizedNode(SyntaxKind.ForOfStatement); node.initializer = initializer; node.expression = expression; node.statement = statement; @@ -933,112 +928,105 @@ namespace ts { } export function updateForOf(node: ForOfStatement, initializer: ForInitializer, expression: Expression, statement: Statement) { - if (node.initializer !== initializer || node.expression !== expression || node.statement !== statement) { - return updateNode(createForOf(initializer, expression, statement, node), node); - } - return node; + return node.initializer !== initializer + || node.expression !== expression + || node.statement !== statement + ? updateNode(createForOf(initializer, expression, statement), node) + : node; } - export function createContinue(label?: Identifier, location?: TextRange): ContinueStatement { - const node = createNode(SyntaxKind.ContinueStatement, location); - if (label) { - node.label = label; - } + export function createContinue(label?: string | Identifier): ContinueStatement { + const node = createSynthesizedNode(SyntaxKind.ContinueStatement); + node.label = asName(label); return node; } export function updateContinue(node: ContinueStatement, label: Identifier) { - if (node.label !== label) { - return updateNode(createContinue(label, node), node); - } - return node; + return node.label !== label + ? updateNode(createContinue(label), node) + : node; } - export function createBreak(label?: Identifier, location?: TextRange): BreakStatement { - const node = createNode(SyntaxKind.BreakStatement, location); - if (label) { - node.label = label; - } + export function createBreak(label?: string | Identifier): BreakStatement { + const node = createSynthesizedNode(SyntaxKind.BreakStatement); + node.label = asName(label); return node; } export function updateBreak(node: BreakStatement, label: Identifier) { - if (node.label !== label) { - return updateNode(createBreak(label, node), node); - } - return node; + return node.label !== label + ? updateNode(createBreak(label), node) + : node; } - export function createReturn(expression?: Expression, location?: TextRange): ReturnStatement { - const node = createNode(SyntaxKind.ReturnStatement, location); + export function createReturn(expression?: Expression): ReturnStatement { + const node = createSynthesizedNode(SyntaxKind.ReturnStatement); node.expression = expression; return node; } export function updateReturn(node: ReturnStatement, expression: Expression) { - if (node.expression !== expression) { - return updateNode(createReturn(expression, /*location*/ node), node); - } - return node; + return node.expression !== expression + ? updateNode(createReturn(expression), node) + : node; } - export function createWith(expression: Expression, statement: Statement, location?: TextRange) { - const node = createNode(SyntaxKind.WithStatement, location); + export function createWith(expression: Expression, statement: Statement) { + const node = createSynthesizedNode(SyntaxKind.WithStatement); node.expression = expression; node.statement = statement; return node; } export function updateWith(node: WithStatement, expression: Expression, statement: Statement) { - if (node.expression !== expression || node.statement !== statement) { - return updateNode(createWith(expression, statement, node), node); - } - return node; + return node.expression !== expression + || node.statement !== statement + ? updateNode(createWith(expression, statement), node) + : node; } - export function createSwitch(expression: Expression, caseBlock: CaseBlock, location?: TextRange): SwitchStatement { - const node = createNode(SyntaxKind.SwitchStatement, location); + export function createSwitch(expression: Expression, caseBlock: CaseBlock): SwitchStatement { + const node = createSynthesizedNode(SyntaxKind.SwitchStatement); node.expression = parenthesizeExpressionForList(expression); node.caseBlock = caseBlock; return node; } export function updateSwitch(node: SwitchStatement, expression: Expression, caseBlock: CaseBlock) { - if (node.expression !== expression || node.caseBlock !== caseBlock) { - return updateNode(createSwitch(expression, caseBlock, node), node); - } - return node; + return node.expression !== expression + || node.caseBlock !== caseBlock + ? updateNode(createSwitch(expression, caseBlock), node) + : node; } - export function createLabel(label: string | Identifier, statement: Statement, location?: TextRange) { - const node = createNode(SyntaxKind.LabeledStatement, location); - node.label = typeof label === "string" ? createIdentifier(label) : label; + export function createLabel(label: string | Identifier, statement: Statement) { + const node = createSynthesizedNode(SyntaxKind.LabeledStatement); + node.label = asName(label); node.statement = statement; return node; } export function updateLabel(node: LabeledStatement, label: Identifier, statement: Statement) { - if (node.label !== label || node.statement !== statement) { - return updateNode(createLabel(label, statement, node), node); - } - return node; + return node.label !== label + || node.statement !== statement + ? updateNode(createLabel(label, statement), node) + : node; } - export function createThrow(expression: Expression, location?: TextRange) { - const node = createNode(SyntaxKind.ThrowStatement, location); + export function createThrow(expression: Expression) { + const node = createSynthesizedNode(SyntaxKind.ThrowStatement); node.expression = expression; return node; } export function updateThrow(node: ThrowStatement, expression: Expression) { - if (node.expression !== expression) { - return updateNode(createThrow(expression, node), node); - } - return node; + return node.expression !== expression + ? updateNode(createThrow(expression), node) + : node; } - export function createTry(tryBlock: Block, catchClause: CatchClause, finallyBlock: Block, location?: TextRange) { - const node = createNode(SyntaxKind.TryStatement, location); + export function createTry(tryBlock: Block, catchClause: CatchClause, finallyBlock: Block) { + const node = createSynthesizedNode(SyntaxKind.TryStatement); node.tryBlock = tryBlock; node.catchClause = catchClause; node.finallyBlock = finallyBlock; @@ -1046,32 +1034,32 @@ namespace ts { } export function updateTry(node: TryStatement, tryBlock: Block, catchClause: CatchClause, finallyBlock: Block) { - if (node.tryBlock !== tryBlock || node.catchClause !== catchClause || node.finallyBlock !== finallyBlock) { - return updateNode(createTry(tryBlock, catchClause, finallyBlock, node), node); - } - return node; + return node.tryBlock !== tryBlock + || node.catchClause !== catchClause + || node.finallyBlock !== finallyBlock + ? updateNode(createTry(tryBlock, catchClause, finallyBlock), node) + : node; } - export function createCaseBlock(clauses: CaseOrDefaultClause[], location?: TextRange): CaseBlock { - const node = createNode(SyntaxKind.CaseBlock, location); + export function createCaseBlock(clauses: CaseOrDefaultClause[]): CaseBlock { + const node = createSynthesizedNode(SyntaxKind.CaseBlock); node.clauses = createNodeArray(clauses); return node; } export function updateCaseBlock(node: CaseBlock, clauses: CaseOrDefaultClause[]) { - if (node.clauses !== clauses) { - return updateNode(createCaseBlock(clauses, node), node); - } - return node; + return node.clauses !== clauses + ? updateNode(createCaseBlock(clauses), node) + : node; } - export function createFunctionDeclaration(decorators: Decorator[], modifiers: Modifier[], asteriskToken: AsteriskToken, name: string | Identifier, typeParameters: TypeParameterDeclaration[], parameters: ParameterDeclaration[], type: TypeNode, body: Block, location?: TextRange, flags?: NodeFlags) { - const node = createNode(SyntaxKind.FunctionDeclaration, location, flags); - node.decorators = decorators ? createNodeArray(decorators) : undefined; - node.modifiers = modifiers ? createNodeArray(modifiers) : undefined; + export function createFunctionDeclaration(decorators: Decorator[], modifiers: Modifier[], asteriskToken: AsteriskToken, name: string | Identifier, typeParameters: TypeParameterDeclaration[], parameters: ParameterDeclaration[], type: TypeNode, body: Block) { + const node = createSynthesizedNode(SyntaxKind.FunctionDeclaration); + node.decorators = asNodeArray(decorators); + node.modifiers = asNodeArray(modifiers); node.asteriskToken = asteriskToken; - node.name = typeof name === "string" ? createIdentifier(name) : name; - node.typeParameters = typeParameters ? createNodeArray(typeParameters) : undefined; + node.name = asName(name); + node.typeParameters = asNodeArray(typeParameters); node.parameters = createNodeArray(parameters); node.type = type; node.body = body; @@ -1079,163 +1067,172 @@ namespace ts { } export function updateFunctionDeclaration(node: FunctionDeclaration, decorators: Decorator[], modifiers: Modifier[], name: Identifier, typeParameters: TypeParameterDeclaration[], parameters: ParameterDeclaration[], type: TypeNode, body: Block) { - if (node.decorators !== decorators || node.modifiers !== modifiers || node.name !== name || node.typeParameters !== typeParameters || node.parameters !== parameters || node.type !== type || node.body !== body) { - return updateNode(createFunctionDeclaration(decorators, modifiers, node.asteriskToken, name, typeParameters, parameters, type, body, /*location*/ node, node.flags), node); - } - return node; + return node.decorators !== decorators + || node.modifiers !== modifiers + || node.name !== name + || node.typeParameters !== typeParameters + || node.parameters !== parameters + || node.type !== type + || node.body !== body + ? updateNode(createFunctionDeclaration(decorators, modifiers, node.asteriskToken, name, typeParameters, parameters, type, body), node) + : node; } - export function createClassDeclaration(decorators: Decorator[], modifiers: Modifier[], name: Identifier, typeParameters: TypeParameterDeclaration[], heritageClauses: HeritageClause[], members: ClassElement[], location?: TextRange) { - const node = createNode(SyntaxKind.ClassDeclaration, location); - node.decorators = decorators ? createNodeArray(decorators) : undefined; - node.modifiers = modifiers ? createNodeArray(modifiers) : undefined; - node.name = name; - node.typeParameters = typeParameters ? createNodeArray(typeParameters) : undefined; - node.heritageClauses = createNodeArray(heritageClauses); + export function createClassDeclaration(decorators: Decorator[], modifiers: Modifier[], name: string | Identifier, typeParameters: TypeParameterDeclaration[], heritageClauses: HeritageClause[], members: ClassElement[]) { + const node = createSynthesizedNode(SyntaxKind.ClassDeclaration); + node.decorators = asNodeArray(decorators); + node.modifiers = asNodeArray(modifiers); + node.name = asName(name); + node.typeParameters = asNodeArray(typeParameters); + node.heritageClauses = asNodeArray(heritageClauses); node.members = createNodeArray(members); return node; } export function updateClassDeclaration(node: ClassDeclaration, decorators: Decorator[], modifiers: Modifier[], name: Identifier, typeParameters: TypeParameterDeclaration[], heritageClauses: HeritageClause[], members: ClassElement[]) { - if (node.decorators !== decorators || node.modifiers !== modifiers || node.name !== name || node.typeParameters !== typeParameters || node.heritageClauses !== heritageClauses || node.members !== members) { - return updateNode(createClassDeclaration(decorators, modifiers, name, typeParameters, heritageClauses, members, node), node); - } - return node; + return node.decorators !== decorators + || node.modifiers !== modifiers + || node.name !== name + || node.typeParameters !== typeParameters + || node.heritageClauses !== heritageClauses + || node.members !== members + ? updateNode(createClassDeclaration(decorators, modifiers, name, typeParameters, heritageClauses, members), node) + : node; } - export function createImportDeclaration(decorators: Decorator[], modifiers: Modifier[], importClause: ImportClause, moduleSpecifier?: Expression, location?: TextRange): ImportDeclaration { - const node = createNode(SyntaxKind.ImportDeclaration, location); - node.decorators = decorators ? createNodeArray(decorators) : undefined; - node.modifiers = modifiers ? createNodeArray(modifiers) : undefined; + export function createImportDeclaration(decorators: Decorator[], modifiers: Modifier[], importClause: ImportClause, moduleSpecifier?: Expression): ImportDeclaration { + const node = createSynthesizedNode(SyntaxKind.ImportDeclaration); + node.decorators = asNodeArray(decorators); + node.modifiers = asNodeArray(modifiers); node.importClause = importClause; node.moduleSpecifier = moduleSpecifier; return node; } export function updateImportDeclaration(node: ImportDeclaration, decorators: Decorator[], modifiers: Modifier[], importClause: ImportClause, moduleSpecifier: Expression) { - if (node.decorators !== decorators || node.modifiers !== modifiers || node.importClause !== importClause || node.moduleSpecifier !== moduleSpecifier) { - return updateNode(createImportDeclaration(decorators, modifiers, importClause, moduleSpecifier, node), node); - } - return node; + return node.decorators !== decorators + || node.modifiers !== modifiers + || node.importClause !== importClause || node.moduleSpecifier !== moduleSpecifier + ? updateNode(createImportDeclaration(decorators, modifiers, importClause, moduleSpecifier), node) + : node; } - export function createImportClause(name: Identifier, namedBindings: NamedImportBindings, location?: TextRange): ImportClause { - const node = createNode(SyntaxKind.ImportClause, location); + export function createImportClause(name: Identifier, namedBindings: NamedImportBindings): ImportClause { + const node = createSynthesizedNode(SyntaxKind.ImportClause); node.name = name; node.namedBindings = namedBindings; return node; } export function updateImportClause(node: ImportClause, name: Identifier, namedBindings: NamedImportBindings) { - if (node.name !== name || node.namedBindings !== namedBindings) { - return updateNode(createImportClause(name, namedBindings, node), node); - } - return node; + return node.name !== name + || node.namedBindings !== namedBindings + ? updateNode(createImportClause(name, namedBindings), node) + : node; } - export function createNamespaceImport(name: Identifier, location?: TextRange): NamespaceImport { - const node = createNode(SyntaxKind.NamespaceImport, location); + export function createNamespaceImport(name: Identifier): NamespaceImport { + const node = createSynthesizedNode(SyntaxKind.NamespaceImport); node.name = name; return node; } export function updateNamespaceImport(node: NamespaceImport, name: Identifier) { - if (node.name !== name) { - return updateNode(createNamespaceImport(name, node), node); - } - return node; + return node.name !== name + ? updateNode(createNamespaceImport(name), node) + : node; } - export function createNamedImports(elements: ImportSpecifier[], location?: TextRange): NamedImports { - const node = createNode(SyntaxKind.NamedImports, location); + export function createNamedImports(elements: ImportSpecifier[]): NamedImports { + const node = createSynthesizedNode(SyntaxKind.NamedImports); node.elements = createNodeArray(elements); return node; } export function updateNamedImports(node: NamedImports, elements: ImportSpecifier[]) { - if (node.elements !== elements) { - return updateNode(createNamedImports(elements, node), node); - } - return node; + return node.elements !== elements + ? updateNode(createNamedImports(elements), node) + : node; } - export function createImportSpecifier(propertyName: Identifier, name: Identifier, location?: TextRange) { - const node = createNode(SyntaxKind.ImportSpecifier, location); + export function createImportSpecifier(propertyName: Identifier, name: Identifier) { + const node = createSynthesizedNode(SyntaxKind.ImportSpecifier); node.propertyName = propertyName; node.name = name; return node; } export function updateImportSpecifier(node: ImportSpecifier, propertyName: Identifier, name: Identifier) { - if (node.propertyName !== propertyName || node.name !== name) { - return updateNode(createImportSpecifier(propertyName, name, node), node); - } - return node; + return node.propertyName !== propertyName + || node.name !== name + ? updateNode(createImportSpecifier(propertyName, name), node) + : node; } - export function createExportAssignment(decorators: Decorator[], modifiers: Modifier[], isExportEquals: boolean, expression: Expression, location?: TextRange) { - const node = createNode(SyntaxKind.ExportAssignment, location); - node.decorators = decorators ? createNodeArray(decorators) : undefined; - node.modifiers = modifiers ? createNodeArray(modifiers) : undefined; + export function createExportAssignment(decorators: Decorator[], modifiers: Modifier[], isExportEquals: boolean, expression: Expression) { + const node = createSynthesizedNode(SyntaxKind.ExportAssignment); + node.decorators = asNodeArray(decorators); + node.modifiers = asNodeArray(modifiers); node.isExportEquals = isExportEquals; node.expression = expression; return node; } export function updateExportAssignment(node: ExportAssignment, decorators: Decorator[], modifiers: Modifier[], expression: Expression) { - if (node.decorators !== decorators || node.modifiers !== modifiers || node.expression !== expression) { - return updateNode(createExportAssignment(decorators, modifiers, node.isExportEquals, expression, node), node); - } - return node; + return node.decorators !== decorators + || node.modifiers !== modifiers + || node.expression !== expression + ? updateNode(createExportAssignment(decorators, modifiers, node.isExportEquals, expression), node) + : node; } - export function createExportDeclaration(decorators: Decorator[], modifiers: Modifier[], exportClause: NamedExports, moduleSpecifier?: Expression, location?: TextRange) { - const node = createNode(SyntaxKind.ExportDeclaration, location); - node.decorators = decorators ? createNodeArray(decorators) : undefined; - node.modifiers = modifiers ? createNodeArray(modifiers) : undefined; + export function createExportDeclaration(decorators: Decorator[], modifiers: Modifier[], exportClause: NamedExports, moduleSpecifier?: Expression) { + const node = createSynthesizedNode(SyntaxKind.ExportDeclaration); + node.decorators = asNodeArray(decorators); + node.modifiers = asNodeArray(modifiers); node.exportClause = exportClause; node.moduleSpecifier = moduleSpecifier; return node; } export function updateExportDeclaration(node: ExportDeclaration, decorators: Decorator[], modifiers: Modifier[], exportClause: NamedExports, moduleSpecifier: Expression) { - if (node.decorators !== decorators || node.modifiers !== modifiers || node.exportClause !== exportClause || node.moduleSpecifier !== moduleSpecifier) { - return updateNode(createExportDeclaration(decorators, modifiers, exportClause, moduleSpecifier, node), node); - } - return node; + return node.decorators !== decorators + || node.modifiers !== modifiers + || node.exportClause !== exportClause + || node.moduleSpecifier !== moduleSpecifier + ? updateNode(createExportDeclaration(decorators, modifiers, exportClause, moduleSpecifier), node) + : node; } - export function createNamedExports(elements: ExportSpecifier[], location?: TextRange) { - const node = createNode(SyntaxKind.NamedExports, location); + export function createNamedExports(elements: ExportSpecifier[]) { + const node = createSynthesizedNode(SyntaxKind.NamedExports); node.elements = createNodeArray(elements); return node; } export function updateNamedExports(node: NamedExports, elements: ExportSpecifier[]) { - if (node.elements !== elements) { - return updateNode(createNamedExports(elements, node), node); - } - return node; + return node.elements !== elements + ? updateNode(createNamedExports(elements), node) + : node; } - export function createExportSpecifier(name: string | Identifier, propertyName?: string | Identifier, location?: TextRange) { - const node = createNode(SyntaxKind.ExportSpecifier, location); - node.name = typeof name === "string" ? createIdentifier(name) : name; - node.propertyName = typeof propertyName === "string" ? createIdentifier(propertyName) : propertyName; + export function createExportSpecifier(name: string | Identifier, propertyName?: string | Identifier) { + const node = createSynthesizedNode(SyntaxKind.ExportSpecifier); + node.name = asName(name); + node.propertyName = asName(propertyName); return node; } export function updateExportSpecifier(node: ExportSpecifier, name: Identifier, propertyName: Identifier) { - if (node.name !== name || node.propertyName !== propertyName) { - return updateNode(createExportSpecifier(name, propertyName, node), node); - } - return node; + return node.name !== name || node.propertyName !== propertyName + ? updateNode(createExportSpecifier(name, propertyName), node) + : node; } // JSX - export function createJsxElement(openingElement: JsxOpeningElement, children: JsxChild[], closingElement: JsxClosingElement, location?: TextRange) { - const node = createNode(SyntaxKind.JsxElement, location); + export function createJsxElement(openingElement: JsxOpeningElement, children: JsxChild[], closingElement: JsxClosingElement) { + const node = createSynthesizedNode(SyntaxKind.JsxElement); node.openingElement = openingElement; node.children = createNodeArray(children); node.closingElement = closingElement; @@ -1243,98 +1240,96 @@ namespace ts { } export function updateJsxElement(node: JsxElement, openingElement: JsxOpeningElement, children: JsxChild[], closingElement: JsxClosingElement) { - if (node.openingElement !== openingElement || node.children !== children || node.closingElement !== closingElement) { - return updateNode(createJsxElement(openingElement, children, closingElement, node), node); - } - return node; + return node.openingElement !== openingElement + || node.children !== children + || node.closingElement !== closingElement + ? updateNode(createJsxElement(openingElement, children, closingElement), node) + : node; } - export function createJsxSelfClosingElement(tagName: JsxTagNameExpression, attributes: JsxAttributeLike[], location?: TextRange) { - const node = createNode(SyntaxKind.JsxSelfClosingElement, location); + export function createJsxSelfClosingElement(tagName: JsxTagNameExpression, attributes: JsxAttributeLike[]) { + const node = createSynthesizedNode(SyntaxKind.JsxSelfClosingElement); node.tagName = tagName; node.attributes = createNodeArray(attributes); return node; } export function updateJsxSelfClosingElement(node: JsxSelfClosingElement, tagName: JsxTagNameExpression, attributes: JsxAttributeLike[]) { - if (node.tagName !== tagName || node.attributes !== attributes) { - return updateNode(createJsxSelfClosingElement(tagName, attributes, node), node); - } - return node; + return node.tagName !== tagName + || node.attributes !== attributes + ? updateNode(createJsxSelfClosingElement(tagName, attributes), node) + : node; } - export function createJsxOpeningElement(tagName: JsxTagNameExpression, attributes: JsxAttributeLike[], location?: TextRange) { - const node = createNode(SyntaxKind.JsxOpeningElement, location); + export function createJsxOpeningElement(tagName: JsxTagNameExpression, attributes: JsxAttributeLike[]) { + const node = createSynthesizedNode(SyntaxKind.JsxOpeningElement); node.tagName = tagName; node.attributes = createNodeArray(attributes); return node; } export function updateJsxOpeningElement(node: JsxOpeningElement, tagName: JsxTagNameExpression, attributes: JsxAttributeLike[]) { - if (node.tagName !== tagName || node.attributes !== attributes) { - return updateNode(createJsxOpeningElement(tagName, attributes, node), node); - } - return node; + return node.tagName !== tagName + || node.attributes !== attributes + ? updateNode(createJsxOpeningElement(tagName, attributes), node) + : node; } - export function createJsxClosingElement(tagName: JsxTagNameExpression, location?: TextRange) { - const node = createNode(SyntaxKind.JsxClosingElement, location); + export function createJsxClosingElement(tagName: JsxTagNameExpression) { + const node = createSynthesizedNode(SyntaxKind.JsxClosingElement); node.tagName = tagName; return node; } export function updateJsxClosingElement(node: JsxClosingElement, tagName: JsxTagNameExpression) { - if (node.tagName !== tagName) { - return updateNode(createJsxClosingElement(tagName, node), node); - } - return node; + return node.tagName !== tagName + ? updateNode(createJsxClosingElement(tagName), node) + : node; } - export function createJsxAttribute(name: Identifier, initializer: StringLiteral | JsxExpression, location?: TextRange) { - const node = createNode(SyntaxKind.JsxAttribute, location); + export function createJsxAttribute(name: Identifier, initializer: StringLiteral | JsxExpression) { + const node = createSynthesizedNode(SyntaxKind.JsxAttribute); node.name = name; node.initializer = initializer; return node; } export function updateJsxAttribute(node: JsxAttribute, name: Identifier, initializer: StringLiteral | JsxExpression) { - if (node.name !== name || node.initializer !== initializer) { - return updateNode(createJsxAttribute(name, initializer, node), node); - } - return node; + return node.name !== name + || node.initializer !== initializer + ? updateNode(createJsxAttribute(name, initializer), node) + : node; } - export function createJsxSpreadAttribute(expression: Expression, location?: TextRange) { - const node = createNode(SyntaxKind.JsxSpreadAttribute, location); + export function createJsxSpreadAttribute(expression: Expression) { + const node = createSynthesizedNode(SyntaxKind.JsxSpreadAttribute); node.expression = expression; return node; } export function updateJsxSpreadAttribute(node: JsxSpreadAttribute, expression: Expression) { - if (node.expression !== expression) { - return updateNode(createJsxSpreadAttribute(expression, node), node); - } - return node; + return node.expression !== expression + ? updateNode(createJsxSpreadAttribute(expression), node) + : node; } - export function createJsxExpression(expression: Expression, dotDotDotToken: Token, location?: TextRange) { - const node = createNode(SyntaxKind.JsxExpression, location); + export function createJsxExpression(expression: Expression, dotDotDotToken: DotDotDotToken) { + const node = createSynthesizedNode(SyntaxKind.JsxExpression); node.dotDotDotToken = dotDotDotToken; node.expression = expression; return node; } export function updateJsxExpression(node: JsxExpression, expression: Expression) { - if (node.expression !== expression) { - return updateNode(createJsxExpression(expression, node.dotDotDotToken, node), node); - } - return node; + return node.expression !== expression + ? updateNode(createJsxExpression(expression, node.dotDotDotToken), node) + : node; } // Clauses - export function createHeritageClause(token: SyntaxKind, types: ExpressionWithTypeArguments[], location?: TextRange) { - const node = createNode(SyntaxKind.HeritageClause, location); + export function createHeritageClause(token: SyntaxKind, types: ExpressionWithTypeArguments[]) { + const node = createSynthesizedNode(SyntaxKind.HeritageClause); node.token = token; node.types = createNodeArray(types); return node; @@ -1342,13 +1337,13 @@ namespace ts { export function updateHeritageClause(node: HeritageClause, types: ExpressionWithTypeArguments[]) { if (node.types !== types) { - return updateNode(createHeritageClause(node.token, types, node), node); + return updateNode(createHeritageClause(node.token, types), node); } return node; } - export function createCaseClause(expression: Expression, statements: Statement[], location?: TextRange) { - const node = createNode(SyntaxKind.CaseClause, location); + export function createCaseClause(expression: Expression, statements: Statement[]) { + const node = createSynthesizedNode(SyntaxKind.CaseClause); node.expression = parenthesizeExpressionForList(expression); node.statements = createNodeArray(statements); return node; @@ -1356,26 +1351,26 @@ namespace ts { export function updateCaseClause(node: CaseClause, expression: Expression, statements: Statement[]) { if (node.expression !== expression || node.statements !== statements) { - return updateNode(createCaseClause(expression, statements, node), node); + return updateNode(createCaseClause(expression, statements), node); } return node; } - export function createDefaultClause(statements: Statement[], location?: TextRange) { - const node = createNode(SyntaxKind.DefaultClause, location); + export function createDefaultClause(statements: Statement[]) { + const node = createSynthesizedNode(SyntaxKind.DefaultClause); node.statements = createNodeArray(statements); return node; } export function updateDefaultClause(node: DefaultClause, statements: Statement[]) { if (node.statements !== statements) { - return updateNode(createDefaultClause(statements, node), node); + return updateNode(createDefaultClause(statements), node); } return node; } - export function createCatchClause(variableDeclaration: string | VariableDeclaration, block: Block, location?: TextRange) { - const node = createNode(SyntaxKind.CatchClause, location); + export function createCatchClause(variableDeclaration: string | VariableDeclaration, block: Block) { + const node = createSynthesizedNode(SyntaxKind.CatchClause); node.variableDeclaration = typeof variableDeclaration === "string" ? createVariableDeclaration(variableDeclaration) : variableDeclaration; node.block = block; return node; @@ -1383,16 +1378,16 @@ namespace ts { export function updateCatchClause(node: CatchClause, variableDeclaration: VariableDeclaration, block: Block) { if (node.variableDeclaration !== variableDeclaration || node.block !== block) { - return updateNode(createCatchClause(variableDeclaration, block, node), node); + return updateNode(createCatchClause(variableDeclaration, block), node); } return node; } // Property assignments - export function createPropertyAssignment(name: string | PropertyName, initializer: Expression, location?: TextRange) { - const node = createNode(SyntaxKind.PropertyAssignment, location); - node.name = typeof name === "string" ? createIdentifier(name) : name; + export function createPropertyAssignment(name: string | PropertyName, initializer: Expression) { + const node = createSynthesizedNode(SyntaxKind.PropertyAssignment); + node.name = asName(name); node.questionToken = undefined; node.initializer = initializer !== undefined ? parenthesizeExpressionForList(initializer) : undefined; return node; @@ -1400,34 +1395,34 @@ namespace ts { export function updatePropertyAssignment(node: PropertyAssignment, name: PropertyName, initializer: Expression) { if (node.name !== name || node.initializer !== initializer) { - return updateNode(createPropertyAssignment(name, initializer, node), node); + return updateNode(createPropertyAssignment(name, initializer), node); } return node; } - export function createShorthandPropertyAssignment(name: string | Identifier, objectAssignmentInitializer: Expression, location?: TextRange) { - const node = createNode(SyntaxKind.ShorthandPropertyAssignment, location); - node.name = typeof name === "string" ? createIdentifier(name) : name; + export function createShorthandPropertyAssignment(name: string | Identifier, objectAssignmentInitializer: Expression) { + const node = createSynthesizedNode(SyntaxKind.ShorthandPropertyAssignment); + node.name = asName(name); node.objectAssignmentInitializer = objectAssignmentInitializer !== undefined ? parenthesizeExpressionForList(objectAssignmentInitializer) : undefined; return node; } - export function createSpreadAssignment(expression: Expression, location?: TextRange) { - const node = createNode(SyntaxKind.SpreadAssignment, location); + export function createSpreadAssignment(expression: Expression) { + const node = createSynthesizedNode(SyntaxKind.SpreadAssignment); node.expression = expression !== undefined ? parenthesizeExpressionForList(expression) : undefined; return node; } export function updateShorthandPropertyAssignment(node: ShorthandPropertyAssignment, name: Identifier, objectAssignmentInitializer: Expression) { if (node.name !== name || node.objectAssignmentInitializer !== objectAssignmentInitializer) { - return updateNode(createShorthandPropertyAssignment(name, objectAssignmentInitializer, node), node); + return updateNode(createShorthandPropertyAssignment(name, objectAssignmentInitializer), node); } return node; } export function updateSpreadAssignment(node: SpreadAssignment, expression: Expression) { if (node.expression !== expression) { - return updateNode(createSpreadAssignment(expression, node), node); + return updateNode(createSpreadAssignment(expression), node); } return node; } @@ -1436,7 +1431,8 @@ namespace ts { export function updateSourceFileNode(node: SourceFile, statements: Statement[]) { if (node.statements !== statements) { - const updated = createNode(SyntaxKind.SourceFile, /*location*/ node, node.flags); + const updated = createSynthesizedNode(SyntaxKind.SourceFile); + updated.flags |= node.flags; updated.statements = createNodeArray(statements); updated.endOfFileToken = node.endOfFileToken; updated.fileName = node.fileName; @@ -1472,6 +1468,17 @@ namespace ts { return node; } + /** + * Creates a shallow, memberwise clone of a node for mutation. + */ + export function getMutableClone(node: T): T { + const clone = getSynthesizedClone(node); + clone.pos = node.pos; + clone.end = node.end; + clone.parent = node.parent; + return clone; + } + // Transformation nodes /** @@ -1481,8 +1488,9 @@ namespace ts { * @param original The original statement. */ export function createNotEmittedStatement(original: Node) { - const node = createNode(SyntaxKind.NotEmittedStatement, /*location*/ original); + const node = createSynthesizedNode(SyntaxKind.NotEmittedStatement); node.original = original; + setTextRange(node, original); return node; } @@ -1490,8 +1498,9 @@ namespace ts { * Creates a synthetic element to act as a placeholder for the end of an emitted declaration in * order to properly emit exports. */ + /* @internal */ export function createEndOfDeclarationMarker(original: Node) { - const node = createNode(SyntaxKind.EndOfDeclarationMarker); + const node = createSynthesizedNode(SyntaxKind.EndOfDeclarationMarker); node.emitNode = {}; node.original = original; return node; @@ -1501,8 +1510,9 @@ namespace ts { * Creates a synthetic element to act as a placeholder for the beginning of a merged declaration in * order to properly emit exports. */ + /* @internal */ export function createMergeDeclarationMarker(original: Node) { - const node = createNode(SyntaxKind.MergeDeclarationMarker); + const node = createSynthesizedNode(SyntaxKind.MergeDeclarationMarker); node.emitNode = {}; node.original = original; return node; @@ -1516,16 +1526,17 @@ namespace ts { * @param original The original outer expression. * @param location The location for the expression. Defaults to the positions from "original" if provided. */ - export function createPartiallyEmittedExpression(expression: Expression, original?: Node, location?: TextRange) { - const node = createNode(SyntaxKind.PartiallyEmittedExpression, /*location*/ location || original); + export function createPartiallyEmittedExpression(expression: Expression, original?: Node) { + const node = createSynthesizedNode(SyntaxKind.PartiallyEmittedExpression); node.expression = expression; node.original = original; + setTextRange(node, original); return node; } export function updatePartiallyEmittedExpression(node: PartiallyEmittedExpression, expression: Expression) { if (node.expression !== expression) { - return updateNode(createPartiallyEmittedExpression(expression, node.original, node), node); + return updateNode(createPartiallyEmittedExpression(expression, node.original), node); } return node; } @@ -1549,14 +1560,14 @@ namespace ts { return createBinary(left, SyntaxKind.CommaToken, right); } - export function createLessThan(left: Expression, right: Expression, location?: TextRange) { - return createBinary(left, SyntaxKind.LessThanToken, right, location); + export function createLessThan(left: Expression, right: Expression) { + return createBinary(left, SyntaxKind.LessThanToken, right); } - export function createAssignment(left: ObjectLiteralExpression | ArrayLiteralExpression, right: Expression, location?: TextRange): DestructuringAssignment; - export function createAssignment(left: Expression, right: Expression, location?: TextRange): BinaryExpression; - export function createAssignment(left: Expression, right: Expression, location?: TextRange) { - return createBinary(left, SyntaxKind.EqualsToken, right, location); + export function createAssignment(left: ObjectLiteralExpression | ArrayLiteralExpression, right: Expression): DestructuringAssignment; + export function createAssignment(left: Expression, right: Expression): BinaryExpression; + export function createAssignment(left: Expression, right: Expression) { + return createBinary(left, SyntaxKind.EqualsToken, right); } export function createStrictEquality(left: Expression, right: Expression) { @@ -1575,8 +1586,8 @@ namespace ts { return createBinary(left, SyntaxKind.MinusToken, right); } - export function createPostfixIncrement(operand: Expression, location?: TextRange) { - return createPostfix(operand, SyntaxKind.PlusPlusToken, location); + export function createPostfixIncrement(operand: Expression) { + return createPostfix(operand, SyntaxKind.PlusPlusToken); } export function createLogicalAnd(left: Expression, right: Expression) { @@ -1595,6 +1606,321 @@ namespace ts { return createVoid(createLiteral(0)); } + export function createExportDefault(expression: Expression) { + return createExportAssignment(/*decorators*/ undefined, /*modifiers*/ undefined, /*isExportEquals*/ false, expression); + } + + export function createExternalModuleExport(exportName: Identifier) { + return createExportDeclaration(/*decorators*/ undefined, /*modifiers*/ undefined, createNamedExports([createExportSpecifier(exportName)])); + } + + // Utilities + + function asName(name: string): Identifier; + function asName(name: Identifier): Identifier; + function asName(name: string | Identifier): Identifier; + function asName(name: string | BindingName): BindingName; + function asName(name: string | PropertyName): PropertyName; + function asName(name: string | Identifier | BindingName | PropertyName) { + return typeof name === "string" ? createIdentifier(name) : name; + } + + function asExpression(value: string | number | Expression) { + return typeof value === "string" || typeof value === "number" ? createLiteral(value) : value; + } + + function asNodeArray(array: T[] | undefined): NodeArray | undefined { + return array ? createNodeArray(array) : undefined; + } + + function asToken(value: TKind | Token): Token { + return typeof value === "number" ? createToken(value) : value; + } + + /** + * Clears any EmitNode entries from parse-tree nodes. + * @param sourceFile A source file. + */ + export function disposeEmitNodes(sourceFile: SourceFile) { + // During transformation we may need to annotate a parse tree node with transient + // transformation properties. As parse tree nodes live longer than transformation + // nodes, we need to make sure we reclaim any memory allocated for custom ranges + // from these nodes to ensure we do not hold onto entire subtrees just for position + // information. We also need to reset these nodes to a pre-transformation state + // for incremental parsing scenarios so that we do not impact later emit. + sourceFile = getSourceFileOfNode(getParseTreeNode(sourceFile)); + const emitNode = sourceFile && sourceFile.emitNode; + const annotatedNodes = emitNode && emitNode.annotatedNodes; + if (annotatedNodes) { + for (const node of annotatedNodes) { + node.emitNode = undefined; + } + } + } + + /** + * Associates a node with the current transformation, initializing + * various transient transformation properties. + * + * @param node The node. + */ + /* @internal */ + export function getOrCreateEmitNode(node: Node) { + if (!node.emitNode) { + if (isParseTreeNode(node)) { + // To avoid holding onto transformation artifacts, we keep track of any + // parse tree node we are annotating. This allows us to clean them up after + // all transformations have completed. + if (node.kind === SyntaxKind.SourceFile) { + return node.emitNode = { annotatedNodes: [node] }; + } + + const sourceFile = getSourceFileOfNode(node); + getOrCreateEmitNode(sourceFile).annotatedNodes.push(node); + } + + node.emitNode = {}; + } + + return node.emitNode; + } + + export function setTextRange(range: T, location: TextRange | undefined): T { + if (location) { + range.pos = location.pos; + range.end = location.end; + } + return range; + } + + /** + * Gets flags that control emit behavior of a node. + * + * @param node The node. + */ + export function getEmitFlags(node: Node) { + const emitNode = node.emitNode; + return emitNode && emitNode.flags; + } + + /** + * Sets flags that control emit behavior of a node. + * + * @param node The node. + * @param emitFlags The NodeEmitFlags for the node. + */ + export function setEmitFlags(node: T, emitFlags: EmitFlags) { + getOrCreateEmitNode(node).flags = emitFlags; + return node; + } + + /** + * Gets a custom text range to use when emitting source maps. + * + * @param node The node. + */ + export function getSourceMapRange(node: Node) { + const emitNode = node.emitNode; + return (emitNode && emitNode.sourceMapRange) || node; + } + + /** + * Sets a custom text range to use when emitting source maps. + * + * @param node The node. + * @param range The text range. + */ + export function setSourceMapRange(node: T, range: TextRange) { + getOrCreateEmitNode(node).sourceMapRange = range; + return node; + } + + /** + * Gets the TextRange to use for source maps for a token of a node. + * + * @param node The node. + * @param token The token. + */ + export function getTokenSourceMapRange(node: Node, token: SyntaxKind) { + const emitNode = node.emitNode; + const tokenSourceMapRanges = emitNode && emitNode.tokenSourceMapRanges; + return tokenSourceMapRanges && tokenSourceMapRanges[token]; + } + + /** + * Sets the TextRange to use for source maps for a token of a node. + * + * @param node The node. + * @param token The token. + * @param range The text range. + */ + export function setTokenSourceMapRange(node: T, token: SyntaxKind, range: TextRange) { + const emitNode = getOrCreateEmitNode(node); + const tokenSourceMapRanges = emitNode.tokenSourceMapRanges || (emitNode.tokenSourceMapRanges = []); + tokenSourceMapRanges[token] = range; + return node; + } + + /** + * Gets a custom text range to use when emitting comments. + * + * @param node The node. + */ + export function getCommentRange(node: Node) { + const emitNode = node.emitNode; + return (emitNode && emitNode.commentRange) || node; + } + + /** + * Sets a custom text range to use when emitting comments. + */ + export function setCommentRange(node: T, range: TextRange) { + getOrCreateEmitNode(node).commentRange = range; + return node; + } + + /** + * Gets the constant value to emit for an expression. + */ + export function getConstantValue(node: PropertyAccessExpression | ElementAccessExpression) { + const emitNode = node.emitNode; + return emitNode && emitNode.constantValue; + } + + /** + * Sets the constant value to emit for an expression. + */ + export function setConstantValue(node: PropertyAccessExpression | ElementAccessExpression, value: number) { + const emitNode = getOrCreateEmitNode(node); + emitNode.constantValue = value; + return node; + } + + /** + * Adds an EmitHelper to a node. + */ + export function addEmitHelper(node: T, helper: EmitHelper): T { + const emitNode = getOrCreateEmitNode(node); + emitNode.helpers = append(emitNode.helpers, helper); + return node; + } + + /** + * Add EmitHelpers to a node. + */ + export function addEmitHelpers(node: T, helpers: EmitHelper[] | undefined): T { + if (some(helpers)) { + const emitNode = getOrCreateEmitNode(node); + for (const helper of helpers) { + if (!contains(emitNode.helpers, helper)) { + emitNode.helpers = append(emitNode.helpers, helper); + } + } + } + return node; + } + + /** + * Removes an EmitHelper from a node. + */ + export function removeEmitHelper(node: Node, helper: EmitHelper): boolean { + const emitNode = node.emitNode; + if (emitNode) { + const helpers = emitNode.helpers; + if (helpers) { + return orderedRemoveItem(helpers, helper); + } + } + return false; + } + + /** + * Gets the EmitHelpers of a node. + */ + export function getEmitHelpers(node: Node): EmitHelper[] | undefined { + const emitNode = node.emitNode; + return emitNode && emitNode.helpers; + } + + /** + * Moves matching emit helpers from a source node to a target node. + */ + export function moveEmitHelpers(source: Node, target: Node, predicate: (helper: EmitHelper) => boolean) { + const sourceEmitNode = source.emitNode; + const sourceEmitHelpers = sourceEmitNode && sourceEmitNode.helpers; + if (!some(sourceEmitHelpers)) return; + + const targetEmitNode = getOrCreateEmitNode(target); + let helpersRemoved = 0; + for (let i = 0; i < sourceEmitHelpers.length; i++) { + const helper = sourceEmitHelpers[i]; + if (predicate(helper)) { + helpersRemoved++; + if (!contains(targetEmitNode.helpers, helper)) { + targetEmitNode.helpers = append(targetEmitNode.helpers, helper); + } + } + else if (helpersRemoved > 0) { + sourceEmitHelpers[i - helpersRemoved] = helper; + } + } + + if (helpersRemoved > 0) { + sourceEmitHelpers.length -= helpersRemoved; + } + } + + /* @internal */ + export function compareEmitHelpers(x: EmitHelper, y: EmitHelper) { + if (x === y) return Comparison.EqualTo; + if (x.priority === y.priority) return Comparison.EqualTo; + if (x.priority === undefined) return Comparison.GreaterThan; + if (y.priority === undefined) return Comparison.LessThan; + return compareValues(x.priority, y.priority); + } + + export function setOriginalNode(node: T, original: Node): T { + node.original = original; + if (original) { + const emitNode = original.emitNode; + if (emitNode) node.emitNode = mergeEmitNode(emitNode, node.emitNode); + } + return node; + } + + function mergeEmitNode(sourceEmitNode: EmitNode, destEmitNode: EmitNode) { + const { + flags, + commentRange, + sourceMapRange, + tokenSourceMapRanges, + constantValue, + helpers + } = sourceEmitNode; + if (!destEmitNode) destEmitNode = {}; + if (flags) destEmitNode.flags = flags; + if (commentRange) destEmitNode.commentRange = commentRange; + if (sourceMapRange) destEmitNode.sourceMapRange = sourceMapRange; + if (tokenSourceMapRanges) destEmitNode.tokenSourceMapRanges = mergeTokenSourceMapRanges(tokenSourceMapRanges, destEmitNode.tokenSourceMapRanges); + if (constantValue !== undefined) destEmitNode.constantValue = constantValue; + if (helpers) destEmitNode.helpers = addRange(destEmitNode.helpers, helpers); + return destEmitNode; + } + + function mergeTokenSourceMapRanges(sourceRanges: TextRange[], destRanges: TextRange[]) { + if (!destRanges) destRanges = []; + for (const key in sourceRanges) { + destRanges[key] = sourceRanges[key]; + } + return destRanges; + } +} + +/* @internal */ +namespace ts { + + // Compound nodes + export type TypeOfTag = "undefined" | "number" | "boolean" | "string" | "symbol" | "object" | "function"; export function createTypeCheck(value: Expression, tag: TypeOfTag) { @@ -1605,35 +1931,43 @@ namespace ts { export function createMemberAccessForPropertyName(target: Expression, memberName: PropertyName, location?: TextRange): MemberExpression { if (isComputedPropertyName(memberName)) { - return createElementAccess(target, memberName.expression, location); + return setTextRange(createElementAccess(target, memberName.expression), location); } else { - const expression = isIdentifier(memberName) ? createPropertyAccess(target, memberName, location) : createElementAccess(target, memberName, location); - (expression.emitNode || (expression.emitNode = {})).flags |= EmitFlags.NoNestedSourceMaps; + const expression = setTextRange( + isIdentifier(memberName) + ? createPropertyAccess(target, memberName) + : createElementAccess(target, memberName), + memberName + ); + getOrCreateEmitNode(expression).flags |= EmitFlags.NoNestedSourceMaps; return expression; } } export function createFunctionCall(func: Expression, thisArg: Expression, argumentsList: Expression[], location?: TextRange) { - return createCall( - createPropertyAccess(func, "call"), - /*typeArguments*/ undefined, - [ - thisArg, - ...argumentsList - ], + return setTextRange( + createCall( + createPropertyAccess(func, "call"), + /*typeArguments*/ undefined, + [ + thisArg, + ...argumentsList + ]), location ); } export function createFunctionApply(func: Expression, thisArg: Expression, argumentsExpression: Expression, location?: TextRange) { - return createCall( - createPropertyAccess(func, "apply"), - /*typeArguments*/ undefined, - [ - thisArg, - argumentsExpression - ], + return setTextRange( + createCall( + createPropertyAccess(func, "apply"), + /*typeArguments*/ undefined, + [ + thisArg, + argumentsExpression + ] + ), location ); } @@ -1656,10 +1990,12 @@ namespace ts { } export function createMathPow(left: Expression, right: Expression, location?: TextRange) { - return createCall( - createPropertyAccess(createIdentifier("Math"), "pow"), - /*typeArguments*/ undefined, - [left, right], + return setTextRange( + createCall( + createPropertyAccess(createIdentifier("Math"), "pow"), + /*typeArguments*/ undefined, + [left, right] + ), location ); } @@ -1679,7 +2015,7 @@ namespace ts { function createJsxFactoryExpressionFromEntityName(jsxFactory: EntityName, parent: JsxOpeningLikeElement): Expression { if (isQualifiedName(jsxFactory)) { const left = createJsxFactoryExpressionFromEntityName(jsxFactory.left, parent); - const right = createSynthesizedNode(SyntaxKind.Identifier); + const right = createIdentifier(jsxFactory.right.text); right.text = jsxFactory.right.text; return createPropertyAccess(left, right); } @@ -1719,34 +2055,16 @@ namespace ts { } } - return createCall( - createJsxFactoryExpression(jsxFactoryEntity, reactNamespace, parentElement), - /*typeArguments*/ undefined, - argumentsList, + return setTextRange( + createCall( + createJsxFactoryExpression(jsxFactoryEntity, reactNamespace, parentElement), + /*typeArguments*/ undefined, + argumentsList + ), location ); } - export function createExportDefault(expression: Expression) { - return createExportAssignment(/*decorators*/ undefined, /*modifiers*/ undefined, /*isExportEquals*/ false, expression); - } - - export function createExternalModuleExport(exportName: Identifier) { - return createExportDeclaration(/*decorators*/ undefined, /*modifiers*/ undefined, createNamedExports([createExportSpecifier(exportName)])); - } - - export function createLetStatement(name: Identifier, initializer: Expression, location?: TextRange) { - return createVariableStatement(/*modifiers*/ undefined, createLetDeclarationList([createVariableDeclaration(name, /*type*/ undefined, initializer)]), location); - } - - export function createLetDeclarationList(declarations: VariableDeclaration[], location?: TextRange) { - return createVariableDeclarationList(declarations, location, NodeFlags.Let); - } - - export function createConstDeclarationList(declarations: VariableDeclaration[], location?: TextRange) { - return createVariableDeclarationList(declarations, location, NodeFlags.Const); - } - // Helpers export function getHelperName(name: string) { @@ -1809,7 +2127,9 @@ namespace ts { } else if (callee.kind === SyntaxKind.SuperKeyword) { thisArg = createThis(); - target = languageVersion < ScriptTarget.ES2015 ? createIdentifier("_super", /*location*/ callee) : callee; + target = languageVersion < ScriptTarget.ES2015 + ? setTextRange(createIdentifier("_super"), callee) + : callee; } else { switch (callee.kind) { @@ -1818,14 +2138,16 @@ namespace ts { // for `a.b()` target is `(_a = a).b` and thisArg is `_a` thisArg = createTempVariable(recordTempVariable); target = createPropertyAccess( - createAssignment( - thisArg, - (callee).expression, - /*location*/ (callee).expression + setTextRange( + createAssignment( + thisArg, + (callee).expression + ), + (callee).expression ), - (callee).name, - /*location*/ callee + (callee).name ); + setTextRange(target, callee); } else { thisArg = (callee).expression; @@ -1839,14 +2161,16 @@ namespace ts { // for `a[b]()` target is `(_a = a)[b]` and thisArg is `_a` thisArg = createTempVariable(recordTempVariable); target = createElementAccess( - createAssignment( - thisArg, - (callee).expression, - /*location*/ (callee).expression + setTextRange( + createAssignment( + thisArg, + (callee).expression + ), + (callee).expression ), - (callee).argumentExpression, - /*location*/ callee + (callee).argumentExpression ); + setTextRange(target, callee); } else { thisArg = (callee).expression; @@ -1876,7 +2200,7 @@ namespace ts { if (isQualifiedName(node)) { const left = createExpressionFromEntityName(node.left); const right = getMutableClone(node.right); - return createPropertyAccess(left, right, /*location*/ node); + return setTextRange(createPropertyAccess(left, right), node); } else { return getMutableClone(node); @@ -1885,7 +2209,7 @@ namespace ts { export function createExpressionForPropertyName(memberName: PropertyName): Expression { if (isIdentifier(memberName)) { - return createLiteral(memberName, /*location*/ undefined); + return createLiteral(memberName); } else if (isComputedPropertyName(memberName)) { return getMutableClone(memberName.expression); @@ -1921,9 +2245,9 @@ namespace ts { /*typeParameters*/ undefined, getAccessor.parameters, /*type*/ undefined, - getAccessor.body, - /*location*/ getAccessor + getAccessor.body ); + setTextRange(getterFunction, getAccessor); setOriginalNode(getterFunction, getAccessor); const getter = createPropertyAssignment("get", getterFunction); properties.push(getter); @@ -1937,25 +2261,27 @@ namespace ts { /*typeParameters*/ undefined, setAccessor.parameters, /*type*/ undefined, - setAccessor.body, - /*location*/ setAccessor + setAccessor.body ); + setTextRange(setterFunction, setAccessor); setOriginalNode(setterFunction, setAccessor); const setter = createPropertyAssignment("set", setterFunction); properties.push(setter); } - properties.push(createPropertyAssignment("enumerable", createLiteral(true))); - properties.push(createPropertyAssignment("configurable", createLiteral(true))); + properties.push(createPropertyAssignment("enumerable", createTrue())); + properties.push(createPropertyAssignment("configurable", createTrue())); - const expression = createCall( - createPropertyAccess(createIdentifier("Object"), "defineProperty"), - /*typeArguments*/ undefined, - [ - receiver, - createExpressionForPropertyName(property.name), - createObjectLiteral(properties, /*location*/ undefined, multiLine) - ], + const expression = setTextRange( + createCall( + createPropertyAccess(createIdentifier("Object"), "defineProperty"), + /*typeArguments*/ undefined, + [ + receiver, + createExpressionForPropertyName(property.name), + createObjectLiteral(properties, multiLine) + ] + ), /*location*/ firstAccessor ); @@ -1968,12 +2294,14 @@ namespace ts { function createExpressionForPropertyAssignment(property: PropertyAssignment, receiver: Expression) { return aggregateTransformFlags( setOriginalNode( - createAssignment( - createMemberAccessForPropertyName(receiver, property.name, /*location*/ property.name), - property.initializer, - /*location*/ property + setTextRange( + createAssignment( + createMemberAccessForPropertyName(receiver, property.name, /*location*/ property.name), + property.initializer + ), + property ), - /*original*/ property + property ) ); } @@ -1981,9 +2309,11 @@ namespace ts { function createExpressionForShorthandPropertyAssignment(property: ShorthandPropertyAssignment, receiver: Expression) { return aggregateTransformFlags( setOriginalNode( - createAssignment( - createMemberAccessForPropertyName(receiver, property.name, /*location*/ property.name), - getSynthesizedClone(property.name), + setTextRange( + createAssignment( + createMemberAccessForPropertyName(receiver, property.name, /*location*/ property.name), + getSynthesizedClone(property.name) + ), /*location*/ property ), /*original*/ property @@ -1994,20 +2324,24 @@ namespace ts { function createExpressionForMethodDeclaration(method: MethodDeclaration, receiver: Expression) { return aggregateTransformFlags( setOriginalNode( - createAssignment( - createMemberAccessForPropertyName(receiver, method.name, /*location*/ method.name), - setOriginalNode( - createFunctionExpression( - method.modifiers, - method.asteriskToken, - /*name*/ undefined, - /*typeParameters*/ undefined, - method.parameters, - /*type*/ undefined, - method.body, - /*location*/ method - ), - /*original*/ method + setTextRange( + createAssignment( + createMemberAccessForPropertyName(receiver, method.name, /*location*/ method.name), + setOriginalNode( + setTextRange( + createFunctionExpression( + method.modifiers, + method.asteriskToken, + /*name*/ undefined, + /*typeParameters*/ undefined, + method.parameters, + /*type*/ undefined, + method.body + ), + /*location*/ method + ), + /*original*/ method + ) ), /*location*/ method ), @@ -2109,7 +2443,8 @@ namespace ts { * @param allowSourceMaps A value indicating whether source maps may be emitted for the name. */ export function getNamespaceMemberName(ns: Identifier, name: Identifier, allowComments?: boolean, allowSourceMaps?: boolean): PropertyAccessExpression { - const qualifiedName = createPropertyAccess(ns, nodeIsSynthesized(name) ? name : getSynthesizedClone(name), /*location*/ name); + const qualifiedName = createPropertyAccess(ns, nodeIsSynthesized(name) ? name : getSynthesizedClone(name)); + setTextRange(qualifiedName, name); let emitFlags: EmitFlags; if (!allowSourceMaps) emitFlags |= EmitFlags.NoSourceMap; if (!allowComments) emitFlags |= EmitFlags.NoComments; @@ -2118,7 +2453,7 @@ namespace ts { } export function convertToFunctionBody(node: ConciseBody, multiLine?: boolean) { - return isBlock(node) ? node : createBlock([createReturn(node, /*location*/ node)], /*location*/ node, multiLine); + return isBlock(node) ? node : setTextRange(createBlock([setTextRange(createReturn(node), node)], multiLine), node); } function isUseStrictPrologue(node: ExpressionStatement): boolean { @@ -2197,10 +2532,13 @@ namespace ts { } if (!foundUseStrict) { - return createNodeArray([ - startOnNewLine(createStatement(createLiteral("use strict"))), - ...statements - ], statements); + return setTextRange( + createNodeArray([ + startOnNewLine(createStatement(createLiteral("use strict"))), + ...statements + ]), + statements + ); } return statements; @@ -2393,7 +2731,7 @@ namespace ts { return condition; } - function parenthesizeSubexpressionOfConditionalExpression(e: Expression): Expression { + export function parenthesizeSubexpressionOfConditionalExpression(e: Expression): Expression { // per ES grammar both 'whenTrue' and 'whenFalse' parts of conditional expression are assignment expressions // so in case when comma expression is introduced as a part of previous transformations // if should be wrapped in parens since comma operator has the lowest precedence @@ -2445,22 +2783,22 @@ namespace ts { return expression; } - return createParen(expression, /*location*/ expression); + return setTextRange(createParen(expression), expression); } export function parenthesizePostfixOperand(operand: Expression) { return isLeftHandSideExpression(operand) ? operand - : createParen(operand, /*location*/ operand); + : setTextRange(createParen(operand), operand); } export function parenthesizePrefixOperand(operand: Expression) { return isUnaryExpression(operand) ? operand - : createParen(operand, /*location*/ operand); + : setTextRange(createParen(operand), operand); } - function parenthesizeListElements(elements: NodeArray) { + export function parenthesizeListElements(elements: NodeArray) { let result: Expression[]; for (let i = 0; i < elements.length; i++) { const element = parenthesizeExpressionForList(elements[i]); @@ -2474,7 +2812,7 @@ namespace ts { } if (result !== undefined) { - return createNodeArray(result, elements, elements.hasTrailingComma); + return setTextRange(createNodeArray(result, elements.hasTrailingComma), elements); } return elements; @@ -2486,7 +2824,7 @@ namespace ts { const commaPrecedence = getOperatorPrecedence(SyntaxKind.BinaryExpression, SyntaxKind.CommaToken); return expressionPrecedence > commaPrecedence ? expression - : createParen(expression, /*location*/ expression); + : setTextRange(createParen(expression), expression); } export function parenthesizeExpressionForExpressionStatement(expression: Expression) { @@ -2496,14 +2834,14 @@ namespace ts { const kind = skipPartiallyEmittedExpressions(callee).kind; if (kind === SyntaxKind.FunctionExpression || kind === SyntaxKind.ArrowFunction) { const mutableCall = getMutableClone(emittedExpression); - mutableCall.expression = createParen(callee, /*location*/ callee); + mutableCall.expression = setTextRange(createParen(callee), callee); return recreatePartiallyEmittedExpressions(expression, mutableCall); } } else { const leftmostExpressionKind = getLeftmostExpression(emittedExpression).kind; if (leftmostExpressionKind === SyntaxKind.ObjectLiteralExpression || leftmostExpressionKind === SyntaxKind.FunctionExpression) { - return createParen(expression, /*location*/ expression); + return setTextRange(createParen(expression), expression); } } @@ -2559,7 +2897,7 @@ namespace ts { export function parenthesizeConciseBody(body: ConciseBody): ConciseBody { const emittedBody = skipPartiallyEmittedExpressions(body); if (emittedBody.kind === SyntaxKind.ObjectLiteralExpression) { - return createParen(body, /*location*/ body); + return setTextRange(createParen(body), body); } return body; @@ -2631,192 +2969,6 @@ namespace ts { return node; } - export function setOriginalNode(node: T, original: Node): T { - node.original = original; - if (original) { - const emitNode = original.emitNode; - if (emitNode) node.emitNode = mergeEmitNode(emitNode, node.emitNode); - } - return node; - } - - function mergeEmitNode(sourceEmitNode: EmitNode, destEmitNode: EmitNode) { - const { - flags, - commentRange, - sourceMapRange, - tokenSourceMapRanges, - constantValue, - helpers - } = sourceEmitNode; - if (!destEmitNode) destEmitNode = {}; - if (flags) destEmitNode.flags = flags; - if (commentRange) destEmitNode.commentRange = commentRange; - if (sourceMapRange) destEmitNode.sourceMapRange = sourceMapRange; - if (tokenSourceMapRanges) destEmitNode.tokenSourceMapRanges = mergeTokenSourceMapRanges(tokenSourceMapRanges, destEmitNode.tokenSourceMapRanges); - if (constantValue !== undefined) destEmitNode.constantValue = constantValue; - if (helpers) destEmitNode.helpers = addRange(destEmitNode.helpers, helpers); - return destEmitNode; - } - - function mergeTokenSourceMapRanges(sourceRanges: TextRange[], destRanges: TextRange[]) { - if (!destRanges) destRanges = []; - for (const key in sourceRanges) { - destRanges[key] = sourceRanges[key]; - } - return destRanges; - } - - /** - * Clears any EmitNode entries from parse-tree nodes. - * @param sourceFile A source file. - */ - export function disposeEmitNodes(sourceFile: SourceFile) { - // During transformation we may need to annotate a parse tree node with transient - // transformation properties. As parse tree nodes live longer than transformation - // nodes, we need to make sure we reclaim any memory allocated for custom ranges - // from these nodes to ensure we do not hold onto entire subtrees just for position - // information. We also need to reset these nodes to a pre-transformation state - // for incremental parsing scenarios so that we do not impact later emit. - sourceFile = getSourceFileOfNode(getParseTreeNode(sourceFile)); - const emitNode = sourceFile && sourceFile.emitNode; - const annotatedNodes = emitNode && emitNode.annotatedNodes; - if (annotatedNodes) { - for (const node of annotatedNodes) { - node.emitNode = undefined; - } - } - } - - /** - * Associates a node with the current transformation, initializing - * various transient transformation properties. - * - * @param node The node. - */ - export function getOrCreateEmitNode(node: Node) { - if (!node.emitNode) { - if (isParseTreeNode(node)) { - // To avoid holding onto transformation artifacts, we keep track of any - // parse tree node we are annotating. This allows us to clean them up after - // all transformations have completed. - if (node.kind === SyntaxKind.SourceFile) { - return node.emitNode = { annotatedNodes: [node] }; - } - - const sourceFile = getSourceFileOfNode(node); - getOrCreateEmitNode(sourceFile).annotatedNodes.push(node); - } - - node.emitNode = {}; - } - - return node.emitNode; - } - - /** - * Gets flags that control emit behavior of a node. - * - * @param node The node. - */ - export function getEmitFlags(node: Node) { - const emitNode = node.emitNode; - return emitNode && emitNode.flags; - } - - /** - * Sets flags that control emit behavior of a node. - * - * @param node The node. - * @param emitFlags The NodeEmitFlags for the node. - */ - export function setEmitFlags(node: T, emitFlags: EmitFlags) { - getOrCreateEmitNode(node).flags = emitFlags; - return node; - } - - /** - * Gets a custom text range to use when emitting source maps. - * - * @param node The node. - */ - export function getSourceMapRange(node: Node) { - const emitNode = node.emitNode; - return (emitNode && emitNode.sourceMapRange) || node; - } - - /** - * Sets a custom text range to use when emitting source maps. - * - * @param node The node. - * @param range The text range. - */ - export function setSourceMapRange(node: T, range: TextRange) { - getOrCreateEmitNode(node).sourceMapRange = range; - return node; - } - - /** - * Gets the TextRange to use for source maps for a token of a node. - * - * @param node The node. - * @param token The token. - */ - export function getTokenSourceMapRange(node: Node, token: SyntaxKind) { - const emitNode = node.emitNode; - const tokenSourceMapRanges = emitNode && emitNode.tokenSourceMapRanges; - return tokenSourceMapRanges && tokenSourceMapRanges[token]; - } - - /** - * Sets the TextRange to use for source maps for a token of a node. - * - * @param node The node. - * @param token The token. - * @param range The text range. - */ - export function setTokenSourceMapRange(node: T, token: SyntaxKind, range: TextRange) { - const emitNode = getOrCreateEmitNode(node); - const tokenSourceMapRanges = emitNode.tokenSourceMapRanges || (emitNode.tokenSourceMapRanges = []); - tokenSourceMapRanges[token] = range; - return node; - } - - /** - * Gets a custom text range to use when emitting comments. - * - * @param node The node. - */ - export function getCommentRange(node: Node) { - const emitNode = node.emitNode; - return (emitNode && emitNode.commentRange) || node; - } - - /** - * Sets a custom text range to use when emitting comments. - */ - export function setCommentRange(node: T, range: TextRange) { - getOrCreateEmitNode(node).commentRange = range; - return node; - } - - /** - * Gets the constant value to emit for an expression. - */ - export function getConstantValue(node: PropertyAccessExpression | ElementAccessExpression) { - const emitNode = node.emitNode; - return emitNode && emitNode.constantValue; - } - - /** - * Sets the constant value to emit for an expression. - */ - export function setConstantValue(node: PropertyAccessExpression | ElementAccessExpression, value: number) { - const emitNode = getOrCreateEmitNode(node); - emitNode.constantValue = value; - return node; - } - export function getExternalHelpersModuleName(node: SourceFile) { const parseNode = getOriginalNode(node, isSourceFile); const emitNode = parseNode && parseNode.emitNode; @@ -2842,110 +2994,6 @@ namespace ts { } } } - /** - * Adds an EmitHelper to a node. - */ - export function addEmitHelper(node: T, helper: EmitHelper): T { - const emitNode = getOrCreateEmitNode(node); - emitNode.helpers = append(emitNode.helpers, helper); - return node; - } - - /** - * Adds an EmitHelper to a node. - */ - export function addEmitHelpers(node: T, helpers: EmitHelper[] | undefined): T { - if (some(helpers)) { - const emitNode = getOrCreateEmitNode(node); - for (const helper of helpers) { - if (!contains(emitNode.helpers, helper)) { - emitNode.helpers = append(emitNode.helpers, helper); - } - } - } - return node; - } - - /** - * Removes an EmitHelper from a node. - */ - export function removeEmitHelper(node: Node, helper: EmitHelper): boolean { - const emitNode = node.emitNode; - if (emitNode) { - const helpers = emitNode.helpers; - if (helpers) { - return orderedRemoveItem(helpers, helper); - } - } - return false; - } - - /** - * Gets the EmitHelpers of a node. - */ - export function getEmitHelpers(node: Node): EmitHelper[] | undefined { - const emitNode = node.emitNode; - return emitNode && emitNode.helpers; - } - - /** - * Moves matching emit helpers from a source node to a target node. - */ - export function moveEmitHelpers(source: Node, target: Node, predicate: (helper: EmitHelper) => boolean) { - const sourceEmitNode = source.emitNode; - const sourceEmitHelpers = sourceEmitNode && sourceEmitNode.helpers; - if (!some(sourceEmitHelpers)) return; - - const targetEmitNode = getOrCreateEmitNode(target); - let helpersRemoved = 0; - for (let i = 0; i < sourceEmitHelpers.length; i++) { - const helper = sourceEmitHelpers[i]; - if (predicate(helper)) { - helpersRemoved++; - if (!contains(targetEmitNode.helpers, helper)) { - targetEmitNode.helpers = append(targetEmitNode.helpers, helper); - } - } - else if (helpersRemoved > 0) { - sourceEmitHelpers[i - helpersRemoved] = helper; - } - } - - if (helpersRemoved > 0) { - sourceEmitHelpers.length -= helpersRemoved; - } - } - - export function compareEmitHelpers(x: EmitHelper, y: EmitHelper) { - if (x === y) return Comparison.EqualTo; - if (x.priority === y.priority) return Comparison.EqualTo; - if (x.priority === undefined) return Comparison.GreaterThan; - if (y.priority === undefined) return Comparison.LessThan; - return compareValues(x.priority, y.priority); - } - - export function setTextRange(node: T, location: TextRange): T { - if (location) { - node.pos = location.pos; - node.end = location.end; - } - return node; - } - - export function setNodeFlags(node: T, flags: NodeFlags): T { - node.flags = flags; - return node; - } - - export function setMultiLine(node: T, multiLine: boolean): T { - node.multiLine = multiLine; - return node; - } - - export function setHasTrailingComma(nodes: NodeArray, hasTrailingComma: boolean): NodeArray { - nodes.hasTrailingComma = hasTrailingComma; - return nodes; - } /** * Get the name of that target module from an import or export declaration @@ -3223,10 +3271,18 @@ namespace ts { if (isBindingElement(element)) { if (element.dotDotDotToken) { Debug.assertNode(element.name, isIdentifier); - return setOriginalNode(createSpread(element.name, element), element); + return setOriginalNode(setTextRange(createSpread(element.name), element), element); } const expression = convertToAssignmentElementTarget(element.name); - return element.initializer ? setOriginalNode(createAssignment(expression, element.initializer, element), element) : expression; + return element.initializer + ? setOriginalNode( + setTextRange( + createAssignment(expression, element.initializer), + element + ), + element + ) + : expression; } Debug.assertNode(element, isExpression); return element; @@ -3236,14 +3292,14 @@ namespace ts { if (isBindingElement(element)) { if (element.dotDotDotToken) { Debug.assertNode(element.name, isIdentifier); - return setOriginalNode(createSpreadAssignment(element.name, element), element); + return setOriginalNode(setTextRange(createSpreadAssignment(element.name), element), element); } if (element.propertyName) { const expression = convertToAssignmentElementTarget(element.name); - return setOriginalNode(createPropertyAssignment(element.propertyName, element.initializer ? createAssignment(expression, element.initializer) : expression, element), element); + return setOriginalNode(setTextRange(createPropertyAssignment(element.propertyName, element.initializer ? createAssignment(expression, element.initializer) : expression), element), element); } Debug.assertNode(element.name, isIdentifier); - return setOriginalNode(createShorthandPropertyAssignment(element.name, element.initializer, element), element); + return setOriginalNode(setTextRange(createShorthandPropertyAssignment(element.name, element.initializer), element), element); } Debug.assertNode(element, isObjectLiteralElementLike); return element; @@ -3263,7 +3319,13 @@ namespace ts { export function convertToObjectAssignmentPattern(node: ObjectBindingOrAssignmentPattern) { if (isObjectBindingPattern(node)) { - return setOriginalNode(createObjectLiteral(map(node.elements, convertToObjectAssignmentElement), node), node); + return setOriginalNode( + setTextRange( + createObjectLiteral(map(node.elements, convertToObjectAssignmentElement)), + node + ), + node + ); } Debug.assertNode(node, isObjectLiteralExpression); return node; @@ -3271,7 +3333,13 @@ namespace ts { export function convertToArrayAssignmentPattern(node: ArrayBindingOrAssignmentPattern) { if (isArrayBindingPattern(node)) { - return setOriginalNode(createArrayLiteral(map(node.elements, convertToArrayAssignmentElement), node), node); + return setOriginalNode( + setTextRange( + createArrayLiteral(map(node.elements, convertToArrayAssignmentElement)), + node + ), + node + ); } Debug.assertNode(node, isArrayLiteralExpression); return node; diff --git a/src/compiler/program.ts b/src/compiler/program.ts index 650711afc79..62f3c066442 100644 --- a/src/compiler/program.ts +++ b/src/compiler/program.ts @@ -1152,13 +1152,10 @@ namespace ts { && (options.isolatedModules || isExternalModuleFile) && !file.isDeclarationFile) { // synthesize 'import "tslib"' declaration - const externalHelpersModuleReference = createSynthesizedNode(SyntaxKind.StringLiteral); - externalHelpersModuleReference.text = externalHelpersModuleNameText; - const importDecl = createSynthesizedNode(SyntaxKind.ImportDeclaration); - - importDecl.parent = file; + const externalHelpersModuleReference = createLiteral(externalHelpersModuleNameText); + const importDecl = createImportDeclaration(undefined, undefined, undefined); externalHelpersModuleReference.parent = importDecl; - + importDecl.parent = file; imports = [externalHelpersModuleReference]; } diff --git a/src/compiler/transformers/destructuring.ts b/src/compiler/transformers/destructuring.ts index 8e32259ff0f..b4473e6a261 100644 --- a/src/compiler/transformers/destructuring.ts +++ b/src/compiler/transformers/destructuring.ts @@ -112,7 +112,10 @@ namespace ts { Debug.assertNode(target, createAssignmentCallback ? isIdentifier : isExpression); const expression = createAssignmentCallback ? createAssignmentCallback(target, value, location) - : createAssignment(visitNode(target, visitor, isExpression), value, location); + : setTextRange( + createAssignment(visitNode(target, visitor, isExpression), value), + location + ); expression.original = original; emitExpression(expression); } @@ -174,9 +177,10 @@ namespace ts { const variable = createVariableDeclaration( name, /*type*/ undefined, - pendingExpressions ? inlineExpressions(append(pendingExpressions, value)) : value, - location); + pendingExpressions ? inlineExpressions(append(pendingExpressions, value)) : value + ); variable.original = original; + setTextRange(variable, location); if (isIdentifier(name)) { setEmitFlags(variable, EmitFlags.NoNestedSourceMaps); } @@ -416,7 +420,7 @@ namespace ts { const temp = createTempVariable(/*recordTempVariable*/ undefined); if (flattenContext.hoistTempVariables) { flattenContext.context.hoistVariableDeclaration(temp); - flattenContext.emitExpression(createAssignment(temp, value, location)); + flattenContext.emitExpression(setTextRange(createAssignment(temp, value), location)); } else { flattenContext.emitBindingOrAssignment(temp, value, location, /*original*/ undefined); @@ -492,6 +496,15 @@ namespace ts { } } } - return createCall(getHelperName("__rest"), undefined, [value, createArrayLiteral(propertyNames, location)]); + return createCall( + getHelperName("__rest"), + undefined, + [ + value, + setTextRange( + createArrayLiteral(propertyNames), + location + ) + ]); } } diff --git a/src/compiler/transformers/es2015.ts b/src/compiler/transformers/es2015.ts index 10ebe648fe2..6d0c9b3c5fa 100644 --- a/src/compiler/transformers/es2015.ts +++ b/src/compiler/transformers/es2015.ts @@ -514,7 +514,7 @@ namespace ts { exitSubtree(ancestorFacts, HierarchyFacts.None, HierarchyFacts.None); return updateSourceFileNode( node, - createNodeArray(statements, node.statements) + setTextRange(createNodeArray(statements), node.statements) ); } @@ -671,9 +671,10 @@ namespace ts { setOriginalNode(variable, node); const statements: Statement[] = []; - const statement = createVariableStatement(/*modifiers*/ undefined, createVariableDeclarationList([variable]), /*location*/ node); + const statement = createVariableStatement(/*modifiers*/ undefined, createVariableDeclarationList([variable])); setOriginalNode(statement, node); + setTextRange(statement, node); startOnNewLine(statement); statements.push(statement); @@ -818,7 +819,7 @@ namespace ts { addRange(statements, endLexicalEnvironment()); - const block = createBlock(createNodeArray(statements, /*location*/ node.members), /*location*/ undefined, /*multiLine*/ true); + const block = createBlock(setTextRange(createNodeArray(statements), /*location*/ node.members), /*multiLine*/ true); setEmitFlags(block, EmitFlags.NoComments); return block; } @@ -833,8 +834,10 @@ namespace ts { function addExtendsHelperIfNeeded(statements: Statement[], node: ClassExpression | ClassDeclaration, extendsClauseElement: ExpressionWithTypeArguments): void { if (extendsClauseElement) { statements.push( - createStatement( - createExtendsHelper(context, getLocalName(node)), + setTextRange( + createStatement( + createExtendsHelper(context, getLocalName(node)) + ), /*location*/ extendsClauseElement ) ); @@ -854,19 +857,18 @@ namespace ts { const ancestorFacts = enterSubtree(HierarchyFacts.ConstructorExcludes, HierarchyFacts.ConstructorIncludes); const constructor = getFirstConstructorWithBody(node); const hasSynthesizedSuper = hasSynthesizedDefaultSuperCall(constructor, extendsClauseElement !== undefined); - const constructorFunction = - createFunctionDeclaration( - /*decorators*/ undefined, - /*modifiers*/ undefined, - /*asteriskToken*/ undefined, - getDeclarationName(node), - /*typeParameters*/ undefined, - transformConstructorParameters(constructor, hasSynthesizedSuper), - /*type*/ undefined, - transformConstructorBody(constructor, node, extendsClauseElement, hasSynthesizedSuper), - /*location*/ constructor || node - ); + const constructorFunction = createFunctionDeclaration( + /*decorators*/ undefined, + /*modifiers*/ undefined, + /*asteriskToken*/ undefined, + getDeclarationName(node), + /*typeParameters*/ undefined, + transformConstructorParameters(constructor, hasSynthesizedSuper), + /*type*/ undefined, + transformConstructorBody(constructor, node, extendsClauseElement, hasSynthesizedSuper) + ); + setTextRange(constructorFunction, constructor || node); if (extendsClauseElement) { setEmitFlags(constructorFunction, EmitFlags.CapturesThis); } @@ -962,14 +964,16 @@ namespace ts { } const block = createBlock( - createNodeArray( - statements, + setTextRange( + createNodeArray( + statements + ), /*location*/ constructor ? constructor.body.statements : node.members ), - /*location*/ constructor ? constructor.body : node, /*multiLine*/ true ); + setTextRange(block, constructor ? constructor.body : node); if (!constructor) { setEmitFlags(block, EmitFlags.NoComments); } @@ -1139,14 +1143,16 @@ namespace ts { // Binding patterns are converted into a generated name and are // evaluated inside the function body. return setOriginalNode( - createParameter( - /*decorators*/ undefined, - /*modifiers*/ undefined, - /*dotDotDotToken*/ undefined, - getGeneratedNameForNode(node), - /*questionToken*/ undefined, - /*type*/ undefined, - /*initializer*/ undefined, + setTextRange( + createParameter( + /*decorators*/ undefined, + /*modifiers*/ undefined, + /*dotDotDotToken*/ undefined, + getGeneratedNameForNode(node), + /*questionToken*/ undefined, + /*type*/ undefined, + /*initializer*/ undefined + ), /*location*/ node ), /*original*/ node @@ -1155,14 +1161,16 @@ namespace ts { else if (node.initializer) { // Initializers are elided return setOriginalNode( - createParameter( - /*decorators*/ undefined, - /*modifiers*/ undefined, - /*dotDotDotToken*/ undefined, - node.name, - /*questionToken*/ undefined, - /*type*/ undefined, - /*initializer*/ undefined, + setTextRange( + createParameter( + /*decorators*/ undefined, + /*modifiers*/ undefined, + /*dotDotDotToken*/ undefined, + node.name, + /*questionToken*/ undefined, + /*type*/ undefined, + /*initializer*/ undefined + ), /*location*/ node ), /*original*/ node @@ -1274,21 +1282,25 @@ namespace ts { const statement = createIf( createTypeCheck(getSynthesizedClone(name), "undefined"), setEmitFlags( - createBlock([ - createStatement( - createAssignment( - setEmitFlags(getMutableClone(name), EmitFlags.NoSourceMap), - setEmitFlags(initializer, EmitFlags.NoSourceMap | getEmitFlags(initializer)), - /*location*/ parameter + setTextRange( + createBlock([ + createStatement( + setTextRange( + createAssignment( + setEmitFlags(getMutableClone(name), EmitFlags.NoSourceMap), + setEmitFlags(initializer, EmitFlags.NoSourceMap | getEmitFlags(initializer)) + ), + parameter + ) ) - ) - ], /*location*/ parameter), + ]), + parameter + ), EmitFlags.SingleLine | EmitFlags.NoTrailingSourceMap | EmitFlags.NoTokenSourceMaps - ), - /*elseStatement*/ undefined, - /*location*/ parameter + ) ); statement.startsOnNewLine = true; + setTextRange(statement, parameter); setEmitFlags(statement, EmitFlags.NoTokenSourceMaps | EmitFlags.NoTrailingSourceMap | EmitFlags.CustomPrologue); statements.push(statement); } @@ -1332,15 +1344,17 @@ namespace ts { // var param = []; statements.push( setEmitFlags( - createVariableStatement( - /*modifiers*/ undefined, - createVariableDeclarationList([ - createVariableDeclaration( - declarationName, - /*type*/ undefined, - createArrayLiteral([]) - ) - ]), + setTextRange( + createVariableStatement( + /*modifiers*/ undefined, + createVariableDeclarationList([ + createVariableDeclaration( + declarationName, + /*type*/ undefined, + createArrayLiteral([]) + ) + ]) + ), /*location*/ parameter ), EmitFlags.CustomPrologue @@ -1351,26 +1365,33 @@ namespace ts { // param[_i - restIndex] = arguments[_i]; // } const forStatement = createFor( - createVariableDeclarationList([ - createVariableDeclaration(temp, /*type*/ undefined, createLiteral(restIndex)) - ], /*location*/ parameter), - createLessThan( - temp, - createPropertyAccess(createIdentifier("arguments"), "length"), - /*location*/ parameter + setTextRange( + createVariableDeclarationList([ + createVariableDeclaration(temp, /*type*/ undefined, createLiteral(restIndex)) + ]), + parameter ), - createPostfixIncrement(temp, /*location*/ parameter), + setTextRange( + createLessThan( + temp, + createPropertyAccess(createIdentifier("arguments"), "length") + ), + parameter + ), + setTextRange(createPostfixIncrement(temp), parameter), createBlock([ startOnNewLine( - createStatement( - createAssignment( - createElementAccess( - expressionName, - restIndex === 0 - ? temp - : createSubtract(temp, createLiteral(restIndex)) - ), - createElementAccess(createIdentifier("arguments"), temp) + setTextRange( + createStatement( + createAssignment( + createElementAccess( + expressionName, + restIndex === 0 + ? temp + : createSubtract(temp, createLiteral(restIndex)) + ), + createElementAccess(createIdentifier("arguments"), temp) + ) ), /*location*/ parameter ) @@ -1405,11 +1426,10 @@ namespace ts { /*type*/ undefined, initializer ) - ]), - originalStatement + ]) ); - setEmitFlags(captureThisStatement, EmitFlags.NoComments | EmitFlags.CustomPrologue); + setTextRange(captureThisStatement, originalStatement); setSourceMapRange(captureThisStatement, node); statements.push(captureThisStatement); } @@ -1529,7 +1549,7 @@ namespace ts { * @param member The SemicolonClassElement node. */ function transformSemicolonClassElementToStatement(member: SemicolonClassElement) { - return createEmptyStatement(/*location*/ member); + return setTextRange(createEmptyStatement(), member); } /** @@ -1547,8 +1567,10 @@ namespace ts { setEmitFlags(memberFunction, EmitFlags.NoComments); setSourceMapRange(memberFunction, sourceMapRange); - const statement = createStatement( - createAssignment(memberName, memberFunction), + const statement = setTextRange( + createStatement( + createAssignment(memberName, memberFunction) + ), /*location*/ member ); @@ -1571,15 +1593,12 @@ namespace ts { * @param accessors The set of related get/set accessors. */ function transformAccessorsToStatement(receiver: LeftHandSideExpression, accessors: AllAccessorDeclarations, container: Node): Statement { - const statement = createStatement( - transformAccessorsToExpression(receiver, accessors, container, /*startsOnNewLine*/ false), - /*location*/ getSourceMapRange(accessors.firstAccessor) - ); - + const statement = createStatement(transformAccessorsToExpression(receiver, accessors, container, /*startsOnNewLine*/ false)); // The location for the statement is used to emit source maps only. // No comments should be emitted for this statement to align with the // old emitter. setEmitFlags(statement, EmitFlags.NoComments); + setSourceMapRange(statement, getSourceMapRange(accessors.firstAccessor)); return statement; } @@ -1622,8 +1641,8 @@ namespace ts { } properties.push( - createPropertyAssignment("enumerable", createLiteral(true)), - createPropertyAssignment("configurable", createLiteral(true)) + createPropertyAssignment("enumerable", createTrue()), + createPropertyAssignment("configurable", createTrue()) ); const call = createCall( @@ -1632,7 +1651,7 @@ namespace ts { [ target, propertyName, - createObjectLiteral(properties, /*location*/ undefined, /*multiLine*/ true) + createObjectLiteral(properties, /*multiLine*/ true) ] ); if (startsOnNewLine) { @@ -1662,9 +1681,9 @@ namespace ts { /*typeParameters*/ undefined, visitParameterList(node.parameters, visitor, context), /*type*/ undefined, - transformFunctionBody(node), - node + transformFunctionBody(node) ); + setTextRange(func, node); setOriginalNode(func, node); setEmitFlags(func, EmitFlags.CapturesThis); exitSubtree(ancestorFacts, HierarchyFacts.None, HierarchyFacts.None); @@ -1758,14 +1777,16 @@ namespace ts { exitSubtree(ancestorFacts, HierarchyFacts.PropagateNewTargetMask, HierarchyFacts.None); convertedLoopState = savedConvertedLoopState; return setOriginalNode( - createFunctionExpression( - /*modifiers*/ undefined, - node.asteriskToken, - name, - /*typeParameters*/ undefined, - parameters, - /*type*/ undefined, - body, + setTextRange( + createFunctionExpression( + /*modifiers*/ undefined, + node.asteriskToken, + name, + /*typeParameters*/ undefined, + parameters, + /*type*/ undefined, + body + ), location ), /*original*/ node @@ -1832,7 +1853,8 @@ namespace ts { } const expression = visitNode(body, visitor, isExpression); - const returnStatement = createReturn(expression, /*location*/ body); + const returnStatement = createReturn(expression); + setTextRange(returnStatement, body); setEmitFlags(returnStatement, EmitFlags.NoTokenSourceMaps | EmitFlags.NoTrailingSourceMap | EmitFlags.NoTrailingComments); statements.push(returnStatement); @@ -1851,7 +1873,8 @@ namespace ts { multiLine = true; } - const block = createBlock(createNodeArray(statements, statementsLocation), node.body, multiLine); + const block = createBlock(setTextRange(createNodeArray(statements), statementsLocation), multiLine); + setTextRange(block, node.body); if (!multiLine && singleLine) { setEmitFlags(block, EmitFlags.SingleLine); } @@ -1868,8 +1891,10 @@ namespace ts { const updated = visitFunctionBody(node.body, functionBodyVisitor, context); return updateBlock( updated, - createNodeArray( - prependCaptureNewTargetIfNeeded(updated.statements, node, /*copyOnWrite*/ true), + setTextRange( + createNodeArray( + prependCaptureNewTargetIfNeeded(updated.statements, node, /*copyOnWrite*/ true) + ), /*location*/ updated.statements ) ); @@ -1969,7 +1994,7 @@ namespace ts { } } if (assignments) { - updated = createStatement(reduceLeft(assignments, (acc, v) => createBinary(v, SyntaxKind.CommaToken, acc)), node); + updated = setTextRange(createStatement(reduceLeft(assignments, (acc, v) => createBinary(v, SyntaxKind.CommaToken, acc))), node); } else { // none of declarations has initializer - the entire variable statement can be deleted @@ -1999,8 +2024,9 @@ namespace ts { ? visitVariableDeclarationInLetDeclarationList : visitVariableDeclaration)); - const declarationList = createVariableDeclarationList(declarations, /*location*/ node); + const declarationList = createVariableDeclarationList(declarations); setOriginalNode(declarationList, node); + setTextRange(declarationList, node); setCommentRange(declarationList, node); if (node.transformFlags & TransformFlags.ContainsBindingPattern @@ -2248,8 +2274,9 @@ namespace ts { elementAccess ); - const declarationList = createVariableDeclarationList(declarations, /*location*/ initializer); + const declarationList = createVariableDeclarationList(declarations); setOriginalNode(declarationList, initializer); + setTextRange(declarationList, initializer); // Adjust the source map range for the first declaration to align with the old // emitter. @@ -2268,19 +2295,24 @@ namespace ts { // The following call does not include the initializer, so we have // to emit it separately. statements.push( - createVariableStatement( - /*modifiers*/ undefined, - setOriginalNode( - createVariableDeclarationList([ - createVariableDeclaration( - firstOriginalDeclaration ? firstOriginalDeclaration.name : createTempVariable(/*recordTempVariable*/ undefined), - /*type*/ undefined, - createElementAccess(rhsReference, counter) - ) - ], /*location*/ moveRangePos(initializer, -1)), - initializer + setTextRange( + createVariableStatement( + /*modifiers*/ undefined, + setOriginalNode( + setTextRange( + createVariableDeclarationList([ + createVariableDeclaration( + firstOriginalDeclaration ? firstOriginalDeclaration.name : createTempVariable(/*recordTempVariable*/ undefined), + /*type*/ undefined, + createElementAccess(rhsReference, counter) + ) + ]), + moveRangePos(initializer, -1) + ), + initializer + ) ), - /*location*/ moveRangeEnd(initializer, -1) + moveRangeEnd(initializer, -1) ) ); } @@ -2306,7 +2338,7 @@ namespace ts { // Currently there is not way to check that assignment is binary expression of destructing assignment // so we have to cast never type to binaryExpression (assignment).end = initializer.end; - statements.push(createStatement(assignment, /*location*/ moveRangeEnd(initializer, -1))); + statements.push(setTextRange(createStatement(assignment), moveRangeEnd(initializer, -1))); } } @@ -2332,33 +2364,38 @@ namespace ts { // The old emitter does not emit source maps for the block. // We add the location to preserve comments. - const body = createBlock( - createNodeArray(statements, /*location*/ statementsLocation), - /*location*/ bodyLocation - ); - + const body = createBlock(setTextRange(createNodeArray(statements), /*location*/ statementsLocation)); + setTextRange(body, bodyLocation); setEmitFlags(body, EmitFlags.NoSourceMap | EmitFlags.NoTokenSourceMaps); const forStatement = createFor( setEmitFlags( - createVariableDeclarationList([ - createVariableDeclaration(counter, /*type*/ undefined, createLiteral(0), /*location*/ moveRangePos(node.expression, -1)), - createVariableDeclaration(rhsReference, /*type*/ undefined, expression, /*location*/ node.expression) - ], /*location*/ node.expression), + setTextRange( + createVariableDeclarationList([ + setTextRange(createVariableDeclaration(counter, /*type*/ undefined, createLiteral(0)), moveRangePos(node.expression, -1)), + setTextRange(createVariableDeclaration(rhsReference, /*type*/ undefined, expression), node.expression) + ]), + node.expression + ), EmitFlags.NoHoisting ), - createLessThan( - counter, - createPropertyAccess(rhsReference, "length"), - /*location*/ node.expression + setTextRange( + createLessThan( + counter, + createPropertyAccess(rhsReference, "length") + ), + node.expression ), - createPostfixIncrement(counter, /*location*/ node.expression), - body, - /*location*/ node + setTextRange( + createPostfixIncrement(counter), + node.expression + ), + body ); // Disable trailing source maps for the OpenParenToken to align source map emit with the old emitter. setEmitFlags(forStatement, EmitFlags.NoTokenTrailingSourceMaps); + setTextRange(forStatement, node); return restoreEnclosingLabel(forStatement, outermostLabeledStatement, convertedLoopState && resetLabel); } @@ -2418,7 +2455,6 @@ namespace ts { setEmitFlags( createObjectLiteral( visitNodes(properties, visitor, isObjectLiteralElementLike, 0, numInitialProperties), - /*location*/ undefined, node.multiLine ), EmitFlags.Indented @@ -2546,14 +2582,14 @@ namespace ts { copyOutParameters(loopOutParameters, CopyDirection.ToOutParameter, statements); } addRange(statements, lexicalEnvironment) - loopBody = createBlock(statements, /*location*/ undefined, /*multiline*/ true); + loopBody = createBlock(statements, /*multiline*/ true); } if (isBlock(loopBody)) { loopBody.multiLine = true; } else { - loopBody = createBlock([loopBody], /*location*/ undefined, /*multiline*/ true); + loopBody = createBlock([loopBody], /*multiline*/ true); } const isAsyncBlockContainingAwait = @@ -2687,12 +2723,7 @@ namespace ts { // visit childnodes to transform initializer/condition/incrementor parts clone = visitEachChild(clone, visitor, context); // set loop statement - clone.statement = createBlock( - convertedLoopBodyStatements, - /*location*/ undefined, - /*multiline*/ true - ); - + clone.statement = createBlock(convertedLoopBodyStatements, /*multiline*/ true); // reset and re-aggregate the transform flags clone.transformFlags = 0; aggregateTransformFlags(clone); @@ -2903,9 +2934,9 @@ namespace ts { receiver, visitNode(property.name, visitor, isPropertyName) ), - visitNode(property.initializer, visitor, isExpression), - /*location*/ property + visitNode(property.initializer, visitor, isExpression) ); + setTextRange(expression, property); if (startsOnNewLine) { expression.startsOnNewLine = true; } @@ -2925,9 +2956,9 @@ namespace ts { receiver, visitNode(property.name, visitor, isPropertyName) ), - getSynthesizedClone(property.name), - /*location*/ property + getSynthesizedClone(property.name) ); + setTextRange(expression, property); if (startsOnNewLine) { expression.startsOnNewLine = true; } @@ -2948,9 +2979,9 @@ namespace ts { receiver, visitNode(method.name, visitor, isPropertyName) ), - transformFunctionLikeToExpression(method, /*location*/ method, /*name*/ undefined, container), - /*location*/ method + transformFunctionLikeToExpression(method, /*location*/ method, /*name*/ undefined, container) ); + setTextRange(expression, method); if (startsOnNewLine) { expression.startsOnNewLine = true; } @@ -2963,7 +2994,8 @@ namespace ts { let updated: CatchClause; if (isBindingPattern(node.variableDeclaration.name)) { const temp = createTempVariable(undefined); - const newVariableDeclaration = createVariableDeclaration(temp, undefined, undefined, node.variableDeclaration); + const newVariableDeclaration = createVariableDeclaration(temp); + setTextRange(newVariableDeclaration, node.variableDeclaration); const vars = flattenDestructuringBinding( node.variableDeclaration, visitor, @@ -2971,8 +3003,9 @@ namespace ts { FlattenLevel.All, temp ); - const list = createVariableDeclarationList(vars, /*location*/node.variableDeclaration, /*flags*/node.variableDeclaration.flags); - const destructure = createVariableStatement(undefined, list); + const list = createVariableDeclarationList(vars); + setTextRange(list, node.variableDeclaration); + const destructure = createVariableStatement(/*modifiers*/ undefined, list); updated = updateCatchClause(node, newVariableDeclaration, addStatementToStartOfBlock(node.block, destructure)); } else { @@ -3001,9 +3034,11 @@ namespace ts { Debug.assert(!isComputedPropertyName(node.name)); const functionExpression = transformFunctionLikeToExpression(node, /*location*/ moveRangePos(node, -1), /*name*/ undefined, /*container*/ undefined); setEmitFlags(functionExpression, EmitFlags.NoLeadingComments | getEmitFlags(functionExpression)); - return createPropertyAssignment( - node.name, - functionExpression, + return setTextRange( + createPropertyAssignment( + node.name, + functionExpression + ), /*location*/ node ); } @@ -3030,9 +3065,11 @@ namespace ts { * @param node A ShorthandPropertyAssignment node. */ function visitShorthandPropertyAssignment(node: ShorthandPropertyAssignment): ObjectLiteralElementLike { - return createPropertyAssignment( - node.name, - getSynthesizedClone(node.name), + return setTextRange( + createPropertyAssignment( + node.name, + getSynthesizedClone(node.name) + ), /*location*/ node ); } @@ -3225,8 +3262,7 @@ namespace ts { function visitSpanOfNonSpreads(chunk: Expression[], multiLine: boolean, hasTrailingComma: boolean): VisitResult { return createArrayLiteral( - visitNodes(createNodeArray(chunk, /*location*/ undefined, hasTrailingComma), visitor, isExpression), - /*location*/ undefined, + visitNodes(createNodeArray(chunk, hasTrailingComma), visitor, isExpression), multiLine ); } @@ -3250,7 +3286,7 @@ namespace ts { * @param node A template literal. */ function visitTemplateLiteral(node: LiteralExpression): LeftHandSideExpression { - return createLiteral(node.text, /*location*/ node); + return setTextRange(createLiteral(node.text), node); } /** @@ -3318,7 +3354,7 @@ namespace ts { // ES6 Spec 11.8.6.1 - Static Semantics of TV's and TRV's // and LineTerminatorSequences are normalized to for both TV and TRV. text = text.replace(/\r\n?/g, "\n"); - return createLiteral(text, /*location*/ node); + return setTextRange(createLiteral(text), node); } /** @@ -3342,7 +3378,8 @@ namespace ts { // "abc" + (1 << 2) + "" const expression = reduceLeft(expressions, createAdd); if (nodeIsSynthesized(expression)) { - setTextRange(expression, node); + expression.pos = node.pos; + expression.end = node.end; } return expression; @@ -3580,7 +3617,7 @@ namespace ts { function substituteThisKeyword(node: PrimaryExpression): PrimaryExpression { if (enabledSubstitutions & ES2015SubstitutionFlags.CapturedThis && hierarchyFacts & HierarchyFacts.CapturesThis) { - return createIdentifier("_this", /*location*/ node); + return setTextRange(createIdentifier("_this"), node); } return node; } diff --git a/src/compiler/transformers/es2016.ts b/src/compiler/transformers/es2016.ts index 5959753fcef..1118e6ad9b6 100644 --- a/src/compiler/transformers/es2016.ts +++ b/src/compiler/transformers/es2016.ts @@ -48,29 +48,37 @@ namespace ts { // Transforms `a[x] **= b` into `(_a = a)[_x = x] = Math.pow(_a[_x], b)` const expressionTemp = createTempVariable(hoistVariableDeclaration); const argumentExpressionTemp = createTempVariable(hoistVariableDeclaration); - target = createElementAccess( - createAssignment(expressionTemp, left.expression, /*location*/ left.expression), - createAssignment(argumentExpressionTemp, left.argumentExpression, /*location*/ left.argumentExpression), - /*location*/ left + target = setTextRange( + createElementAccess( + setTextRange(createAssignment(expressionTemp, left.expression), left.expression), + setTextRange(createAssignment(argumentExpressionTemp, left.argumentExpression), left.argumentExpression) + ), + left ); - value = createElementAccess( - expressionTemp, - argumentExpressionTemp, - /*location*/ left + value = setTextRange( + createElementAccess( + expressionTemp, + argumentExpressionTemp + ), + left ); } else if (isPropertyAccessExpression(left)) { // Transforms `a.x **= b` into `(_a = a).x = Math.pow(_a.x, b)` const expressionTemp = createTempVariable(hoistVariableDeclaration); - target = createPropertyAccess( - createAssignment(expressionTemp, left.expression, /*location*/ left.expression), - left.name, - /*location*/ left + target = setTextRange( + createPropertyAccess( + setTextRange(createAssignment(expressionTemp, left.expression), left.expression), + left.name + ), + left ); - value = createPropertyAccess( - expressionTemp, - left.name, - /*location*/ left + value = setTextRange( + createPropertyAccess( + expressionTemp, + left.name + ), + left ); } else { @@ -78,7 +86,13 @@ namespace ts { target = left; value = left; } - return createAssignment(target, createMathPow(value, right, /*location*/ node), /*location*/ node); + return setTextRange( + createAssignment( + target, + createMathPow(value, right, /*location*/ node) + ), + node + ); } function visitExponentiationExpression(node: BinaryExpression) { diff --git a/src/compiler/transformers/es2017.ts b/src/compiler/transformers/es2017.ts index a7f7b0da0ea..b437298656c 100644 --- a/src/compiler/transformers/es2017.ts +++ b/src/compiler/transformers/es2017.ts @@ -104,10 +104,12 @@ namespace ts { */ function visitAwaitExpression(node: AwaitExpression): Expression { return setOriginalNode( - createYield( - /*asteriskToken*/ undefined, - visitNode(node.expression, visitor, isExpression), - /*location*/ node + setTextRange( + createYield( + /*asteriskToken*/ undefined, + visitNode(node.expression, visitor, isExpression) + ), + node ), node ); @@ -238,7 +240,8 @@ namespace ts { addRange(statements, endLexicalEnvironment()); - const block = createBlock(statements, /*location*/ node.body, /*multiLine*/ true); + const block = createBlock(statements, /*multiLine*/ true); + setTextRange(block, node.body); // Minor optimization, emit `_super` helper to capture `super` access in an arrow. // This step isn't needed if we eventually transform this to ES5. @@ -266,7 +269,7 @@ namespace ts { const declarations = endLexicalEnvironment(); if (some(declarations)) { const block = convertToFunctionBody(expression); - return updateBlock(block, createNodeArray(concatenate(block.statements, declarations), block.statements)); + return updateBlock(block, setTextRange(createNodeArray(concatenate(block.statements, declarations)), block.statements)); } return expression; @@ -281,7 +284,7 @@ namespace ts { startLexicalEnvironment(); const visited = convertToFunctionBody(visitNode(body, visitor, isConciseBody)); const declarations = endLexicalEnvironment(); - return updateBlock(visited, createNodeArray(concatenate(visited.statements, declarations), visited.statements)); + return updateBlock(visited, setTextRange(createNodeArray(concatenate(visited.statements, declarations)), visited.statements)); } } @@ -431,21 +434,25 @@ namespace ts { function createSuperAccessInAsyncMethod(argumentExpression: Expression, flags: NodeCheckFlags, location: TextRange): LeftHandSideExpression { if (flags & NodeCheckFlags.AsyncMethodWithSuperBinding) { - return createPropertyAccess( + return setTextRange( + createPropertyAccess( + createCall( + createIdentifier("_super"), + /*typeArguments*/ undefined, + [argumentExpression] + ), + "value" + ), + location + ); + } + else { + return setTextRange( createCall( createIdentifier("_super"), /*typeArguments*/ undefined, [argumentExpression] ), - "value", - location - ); - } - else { - return createCall( - createIdentifier("_super"), - /*typeArguments*/ undefined, - [argumentExpression], location ); } diff --git a/src/compiler/transformers/es5.ts b/src/compiler/transformers/es5.ts index 8b030642a89..bcecb86e75d 100644 --- a/src/compiler/transformers/es5.ts +++ b/src/compiler/transformers/es5.ts @@ -87,7 +87,7 @@ namespace ts { function substitutePropertyAccessExpression(node: PropertyAccessExpression): Expression { const literalName = trySubstituteReservedName(node.name); if (literalName) { - return createElementAccess(node.expression, literalName, /*location*/ node); + return setTextRange(createElementAccess(node.expression, literalName), node); } return node; } @@ -113,7 +113,7 @@ namespace ts { function trySubstituteReservedName(name: Identifier) { const token = name.originalKeywordKind || (nodeIsSynthesized(name) ? stringToToken(name.text) : undefined); if (token >= SyntaxKind.FirstReservedWord && token <= SyntaxKind.LastReservedWord) { - return createLiteral(name, /*location*/ name); + return setTextRange(createLiteral(name), name); } return undefined; } diff --git a/src/compiler/transformers/esnext.ts b/src/compiler/transformers/esnext.ts index 8b5a095a17e..f058e627df7 100644 --- a/src/compiler/transformers/esnext.ts +++ b/src/compiler/transformers/esnext.ts @@ -210,36 +210,40 @@ namespace ts { const statement = createVariableStatement( /*modifiers*/ undefined, updateVariableDeclarationList(initializer, declarations), - /*location*/ initializer ); + setTextRange(statement, initializer); leadingStatements = append(leadingStatements, statement); } } else if (isAssignmentPattern(initializer)) { temp = createTempVariable(/*recordTempVariable*/ undefined); const expression = flattenDestructuringAssignment( - aggregateTransformFlags(createAssignment(initializer, temp, /*location*/ node.initializer)), + aggregateTransformFlags( + setTextRange( + createAssignment(initializer, temp), + node.initializer + ) + ), visitor, context, FlattenLevel.ObjectRest ); - leadingStatements = append(leadingStatements, createStatement(expression, /*location*/ node.initializer)); + leadingStatements = append(leadingStatements, setTextRange(createStatement(expression), node.initializer)); } } if (temp) { const expression = visitNode(node.expression, visitor, isExpression); const statement = visitNode(node.statement, visitor, isStatement); const block = isBlock(statement) - ? updateBlock(statement, createNodeArray(concatenate(leadingStatements, statement.statements), statement.statements)) - : createBlock(append(leadingStatements, statement), statement, /*multiLine*/ true); + ? updateBlock(statement, setTextRange(createNodeArray(concatenate(leadingStatements, statement.statements)), statement.statements)) + : setTextRange(createBlock(append(leadingStatements, statement), /*multiLine*/ true), statement); return updateForOf( node, - createVariableDeclarationList( - [ - createVariableDeclaration(temp, /*type*/ undefined, /*initializer*/ undefined, node.initializer) - ], - node.initializer, - NodeFlags.Let + setTextRange( + createVariableDeclarationList([ + setTextRange(createVariableDeclaration(temp), node.initializer) + ], NodeFlags.Let), + node.initializer ), expression, block @@ -380,7 +384,7 @@ namespace ts { const trailingStatements = endLexicalEnvironment(); if (some(leadingStatements) || some(trailingStatements)) { const block = convertToFunctionBody(body, /*multiLine*/ true); - return updateBlock(block, createNodeArray(concatenate(concatenate(leadingStatements, block.statements), trailingStatements), block.statements)); + return updateBlock(block, setTextRange(createNodeArray(concatenate(concatenate(leadingStatements, block.statements), trailingStatements)), block.statements)); } return body; } diff --git a/src/compiler/transformers/generators.ts b/src/compiler/transformers/generators.ts index ee17bdacbaf..cabd5d2a96d 100644 --- a/src/compiler/transformers/generators.ts +++ b/src/compiler/transformers/generators.ts @@ -450,15 +450,17 @@ namespace ts { // Currently, we only support generators that were originally async functions. if (node.asteriskToken && getEmitFlags(node) & EmitFlags.AsyncFunctionBody) { node = setOriginalNode( - createFunctionDeclaration( - /*decorators*/ undefined, - node.modifiers, - /*asteriskToken*/ undefined, - node.name, - /*typeParameters*/ undefined, - visitParameterList(node.parameters, visitor, context), - /*type*/ undefined, - transformGeneratorFunctionBody(node.body), + setTextRange( + createFunctionDeclaration( + /*decorators*/ undefined, + node.modifiers, + /*asteriskToken*/ undefined, + node.name, + /*typeParameters*/ undefined, + visitParameterList(node.parameters, visitor, context), + /*type*/ undefined, + transformGeneratorFunctionBody(node.body) + ), /*location*/ node ), node @@ -498,14 +500,16 @@ namespace ts { // Currently, we only support generators that were originally async functions. if (node.asteriskToken && getEmitFlags(node) & EmitFlags.AsyncFunctionBody) { node = setOriginalNode( - createFunctionExpression( - /*modifiers*/ undefined, - /*asteriskToken*/ undefined, - node.name, - /*typeParameters*/ undefined, - visitParameterList(node.parameters, visitor, context), - /*type*/ undefined, - transformGeneratorFunctionBody(node.body), + setTextRange( + createFunctionExpression( + /*modifiers*/ undefined, + /*asteriskToken*/ undefined, + node.name, + /*typeParameters*/ undefined, + visitParameterList(node.parameters, visitor, context), + /*type*/ undefined, + transformGeneratorFunctionBody(node.body) + ), /*location*/ node ), node @@ -606,7 +610,7 @@ namespace ts { operationLocations = savedOperationLocations; state = savedState; - return createBlock(statements, /*location*/ body, body.multiLine); + return setTextRange(createBlock(statements, body.multiLine), body); } /** @@ -739,14 +743,17 @@ namespace ts { const operator = node.operatorToken.kind; if (isCompoundAssignment(operator)) { - return createBinary( - target, - SyntaxKind.EqualsToken, - createBinary( - cacheExpression(target), - getOperatorForCompoundAssignment(operator), - visitNode(right, visitor, isExpression), - node + return setTextRange( + createAssignment( + target, + setTextRange( + createBinary( + cacheExpression(target), + getOperatorForCompoundAssignment(operator), + visitNode(right, visitor, isExpression) + ), + node + ) ), node ); @@ -988,8 +995,11 @@ namespace ts { const expressions = reduceLeft(elements, reduceElement, [], numInitialElements); return hasAssignedTemp - ? createArrayConcat(temp, [createArrayLiteral(expressions, /*location*/ undefined, multiLine)]) - : createArrayLiteral(leadingElement ? [leadingElement, ...expressions] : expressions, location, multiLine); + ? createArrayConcat(temp, [createArrayLiteral(expressions, multiLine)]) + : setTextRange( + createArrayLiteral(leadingElement ? [leadingElement, ...expressions] : expressions, multiLine), + location + ); function reduceElement(expressions: Expression[], element: Expression) { if (containsYield(element) && expressions.length > 0) { @@ -998,11 +1008,10 @@ namespace ts { hasAssignedTemp ? createArrayConcat( temp, - [createArrayLiteral(expressions, /*location*/ undefined, multiLine)] + [createArrayLiteral(expressions, multiLine)] ) : createArrayLiteral( leadingElement ? [leadingElement, ...expressions] : expressions, - /*location*/ undefined, multiLine ) ); @@ -1043,7 +1052,6 @@ namespace ts { emitAssignment(temp, createObjectLiteral( visitNodes(properties, visitor, isObjectLiteralElementLike, 0, numInitialProperties), - /*location*/ undefined, multiLine ) ); @@ -1139,18 +1147,20 @@ namespace ts { const { target, thisArg } = createCallBinding(createPropertyAccess(node.expression, "bind"), hoistVariableDeclaration); return setOriginalNode( - createNew( - createFunctionApply( - cacheExpression(visitNode(target, visitor, isExpression)), - thisArg, - visitElements( - node.arguments, - /*leadingElement*/ createVoidZero() - ) + setTextRange( + createNew( + createFunctionApply( + cacheExpression(visitNode(target, visitor, isExpression)), + thisArg, + visitElements( + node.arguments, + /*leadingElement*/ createVoidZero() + ) + ), + /*typeArguments*/ undefined, + [] ), - /*typeArguments*/ undefined, - [], - /*location*/ node + node ), node ); @@ -1423,9 +1433,11 @@ namespace ts { } else { emitStatement( - createStatement( - visitNode(initializer, visitor, isExpression), - /*location*/ initializer + setTextRange( + createStatement( + visitNode(initializer, visitor, isExpression) + ), + initializer ) ); } @@ -1441,9 +1453,11 @@ namespace ts { markLabel(incrementLabel); if (node.incrementor) { emitStatement( - createStatement( - visitNode(node.incrementor, visitor, isExpression), - /*location*/ node.incrementor + setTextRange( + createStatement( + visitNode(node.incrementor, visitor, isExpression) + ), + node.incrementor ) ); } @@ -2417,11 +2431,13 @@ namespace ts { */ function createInlineBreak(label: Label, location?: TextRange): ReturnStatement { Debug.assert(label > 0, `Invalid label: ${label}`); - return createReturn( - createArrayLiteral([ - createInstruction(Instruction.Break), - createLabel(label) - ]), + return setTextRange( + createReturn( + createArrayLiteral([ + createInstruction(Instruction.Break), + createLabel(label) + ]) + ), location ); } @@ -2433,10 +2449,12 @@ namespace ts { * @param location An optional source map location for the statement. */ function createInlineReturn(expression?: Expression, location?: TextRange): ReturnStatement { - return createReturn( - createArrayLiteral(expression - ? [createInstruction(Instruction.Return), expression] - : [createInstruction(Instruction.Return)] + return setTextRange( + createReturn( + createArrayLiteral(expression + ? [createInstruction(Instruction.Return), expression] + : [createInstruction(Instruction.Return)] + ) ), location ); @@ -2446,7 +2464,14 @@ namespace ts { * Creates an expression that can be used to resume from a Yield operation. */ function createGeneratorResume(location?: TextRange): LeftHandSideExpression { - return createCall(createPropertyAccess(state, "sent"), /*typeArguments*/ undefined, [], location); + return setTextRange( + createCall( + createPropertyAccess(state, "sent"), + /*typeArguments*/ undefined, + [] + ), + location + ); } /** @@ -2614,7 +2639,6 @@ namespace ts { /*type*/ undefined, createBlock( buildResult, - /*location*/ undefined, /*multiLine*/ buildResult.length > 0 ) ), @@ -2944,7 +2968,7 @@ namespace ts { * @param operationLocation The source map location for the operation. */ function writeAssign(left: Expression, right: Expression, operationLocation: TextRange): void { - writeStatement(createStatement(createAssignment(left, right), operationLocation)); + writeStatement(setTextRange(createStatement(createAssignment(left, right)), operationLocation)); } /** @@ -2956,7 +2980,7 @@ namespace ts { function writeThrow(expression: Expression, operationLocation: TextRange): void { lastOperationWasAbrupt = true; lastOperationWasCompletion = true; - writeStatement(createThrow(expression, operationLocation)); + writeStatement(setTextRange(createThrow(expression), operationLocation)); } /** @@ -2970,10 +2994,12 @@ namespace ts { lastOperationWasCompletion = true; writeStatement( setEmitFlags( - createReturn( - createArrayLiteral(expression - ? [createInstruction(Instruction.Return), expression] - : [createInstruction(Instruction.Return)] + setTextRange( + createReturn( + createArrayLiteral(expression + ? [createInstruction(Instruction.Return), expression] + : [createInstruction(Instruction.Return)] + ) ), operationLocation ), @@ -2992,11 +3018,13 @@ namespace ts { lastOperationWasAbrupt = true; writeStatement( setEmitFlags( - createReturn( - createArrayLiteral([ - createInstruction(Instruction.Break), - createLabel(label) - ]), + setTextRange( + createReturn( + createArrayLiteral([ + createInstruction(Instruction.Break), + createLabel(label) + ]) + ), operationLocation ), EmitFlags.NoTokenSourceMaps @@ -3017,11 +3045,13 @@ namespace ts { createIf( condition, setEmitFlags( - createReturn( - createArrayLiteral([ - createInstruction(Instruction.Break), - createLabel(label) - ]), + setTextRange( + createReturn( + createArrayLiteral([ + createInstruction(Instruction.Break), + createLabel(label) + ]) + ), operationLocation ), EmitFlags.NoTokenSourceMaps @@ -3045,11 +3075,13 @@ namespace ts { createIf( createLogicalNot(condition), setEmitFlags( - createReturn( - createArrayLiteral([ - createInstruction(Instruction.Break), - createLabel(label) - ]), + setTextRange( + createReturn( + createArrayLiteral([ + createInstruction(Instruction.Break), + createLabel(label) + ]) + ), operationLocation ), EmitFlags.NoTokenSourceMaps @@ -3070,11 +3102,13 @@ namespace ts { lastOperationWasAbrupt = true; writeStatement( setEmitFlags( - createReturn( - createArrayLiteral( - expression - ? [createInstruction(Instruction.Yield), expression] - : [createInstruction(Instruction.Yield)] + setTextRange( + createReturn( + createArrayLiteral( + expression + ? [createInstruction(Instruction.Yield), expression] + : [createInstruction(Instruction.Yield)] + ) ), operationLocation ), @@ -3093,11 +3127,13 @@ namespace ts { lastOperationWasAbrupt = true; writeStatement( setEmitFlags( - createReturn( - createArrayLiteral([ - createInstruction(Instruction.YieldStar), - expression - ]), + setTextRange( + createReturn( + createArrayLiteral([ + createInstruction(Instruction.YieldStar), + expression + ]) + ), operationLocation ), EmitFlags.NoTokenSourceMaps diff --git a/src/compiler/transformers/jsx.ts b/src/compiler/transformers/jsx.ts index 1307a7f8551..60053d98e57 100644 --- a/src/compiler/transformers/jsx.ts +++ b/src/compiler/transformers/jsx.ts @@ -143,15 +143,15 @@ namespace ts { function transformJsxAttributeInitializer(node: StringLiteral | JsxExpression) { if (node === undefined) { - return createLiteral(true); + return createTrue(); } else if (node.kind === SyntaxKind.StringLiteral) { const decoded = tryDecodeEntities((node).text); - return decoded ? createLiteral(decoded, /*location*/ node) : node; + return decoded ? setTextRange(createLiteral(decoded), node) : node; } else if (node.kind === SyntaxKind.JsxExpression) { if (node.expression === undefined) { - return createLiteral(true); + return createTrue(); } return visitJsxExpression(node); } diff --git a/src/compiler/transformers/module/es2015.ts b/src/compiler/transformers/module/es2015.ts index 86fa1295f7b..cc197073c32 100644 --- a/src/compiler/transformers/module/es2015.ts +++ b/src/compiler/transformers/module/es2015.ts @@ -37,7 +37,7 @@ namespace ts { addRange(statements, visitNodes(node.statements, visitor, isStatement, statementOffset)); return updateSourceFileNode( node, - createNodeArray(statements, node.statements)); + setTextRange(createNodeArray(statements), node.statements)); } else { return visitEachChild(node, visitor, context); diff --git a/src/compiler/transformers/module/module.ts b/src/compiler/transformers/module/module.ts index e072429292a..f6e51fa9fdd 100644 --- a/src/compiler/transformers/module/module.ts +++ b/src/compiler/transformers/module/module.ts @@ -88,7 +88,7 @@ namespace ts { addRange(statements, endLexicalEnvironment()); addExportEqualsIfNeeded(statements, /*emitAsReturn*/ false); - const updated = updateSourceFileNode(node, createNodeArray(statements, node.statements)); + const updated = updateSourceFileNode(node, setTextRange(createNodeArray(statements), node.statements)); if (currentModuleInfo.hasExportStarsToExportValues) { addEmitHelper(updated, exportStarHelper); } @@ -131,47 +131,49 @@ namespace ts { // Create an updated SourceFile: // // define(moduleName?, ["module1", "module2"], function ... - return updateSourceFileNode(node, createNodeArray( - [ - createStatement( - createCall( - define, - /*typeArguments*/ undefined, - [ - // Add the module name (if provided). - ...(moduleName ? [moduleName] : []), + return updateSourceFileNode(node, + setTextRange( + createNodeArray([ + createStatement( + createCall( + define, + /*typeArguments*/ undefined, + [ + // Add the module name (if provided). + ...(moduleName ? [moduleName] : []), - // Add the dependency array argument: - // - // ["require", "exports", module1", "module2", ...] - createArrayLiteral([ - createLiteral("require"), - createLiteral("exports"), - ...aliasedModuleNames, - ...unaliasedModuleNames - ]), + // Add the dependency array argument: + // + // ["require", "exports", module1", "module2", ...] + createArrayLiteral([ + createLiteral("require"), + createLiteral("exports"), + ...aliasedModuleNames, + ...unaliasedModuleNames + ]), - // Add the module body function argument: - // - // function (require, exports, module1, module2) ... - createFunctionExpression( - /*modifiers*/ undefined, - /*asteriskToken*/ undefined, - /*name*/ undefined, - /*typeParameters*/ undefined, - [ - createParameter(/*decorators*/ undefined, /*modifiers*/ undefined, /*dotDotDotToken*/ undefined, "require"), - createParameter(/*decorators*/ undefined, /*modifiers*/ undefined, /*dotDotDotToken*/ undefined, "exports"), - ...importAliasNames - ], - /*type*/ undefined, - transformAsynchronousModuleBody(node) - ) - ] + // Add the module body function argument: + // + // function (require, exports, module1, module2) ... + createFunctionExpression( + /*modifiers*/ undefined, + /*asteriskToken*/ undefined, + /*name*/ undefined, + /*typeParameters*/ undefined, + [ + createParameter(/*decorators*/ undefined, /*modifiers*/ undefined, /*dotDotDotToken*/ undefined, "require"), + createParameter(/*decorators*/ undefined, /*modifiers*/ undefined, /*dotDotDotToken*/ undefined, "exports"), + ...importAliasNames + ], + /*type*/ undefined, + transformAsynchronousModuleBody(node) + ) + ] + ) ) - ) - ], - /*location*/ node.statements) + ]), + /*location*/ node.statements + ) ); } @@ -189,74 +191,76 @@ namespace ts { /*typeParameters*/ undefined, [createParameter(/*decorators*/ undefined, /*modifiers*/ undefined, /*dotDotDotToken*/ undefined, "factory")], /*type*/ undefined, - createBlock( - [ - createIf( - createLogicalAnd( - createTypeCheck(createIdentifier("module"), "object"), - createTypeCheck(createPropertyAccess(createIdentifier("module"), "exports"), "object") - ), - createBlock([ - createVariableStatement( - /*modifiers*/ undefined, - [ - createVariableDeclaration( - "v", - /*type*/ undefined, + setTextRange( + createBlock( + [ + createIf( + createLogicalAnd( + createTypeCheck(createIdentifier("module"), "object"), + createTypeCheck(createPropertyAccess(createIdentifier("module"), "exports"), "object") + ), + createBlock([ + createVariableStatement( + /*modifiers*/ undefined, + [ + createVariableDeclaration( + "v", + /*type*/ undefined, + createCall( + createIdentifier("factory"), + /*typeArguments*/ undefined, + [ + createIdentifier("require"), + createIdentifier("exports") + ] + ) + ) + ] + ), + setEmitFlags( + createIf( + createStrictInequality( + createIdentifier("v"), + createIdentifier("undefined") + ), + createStatement( + createAssignment( + createPropertyAccess(createIdentifier("module"), "exports"), + createIdentifier("v") + ) + ) + ), + EmitFlags.SingleLine + ) + ]), + createIf( + createLogicalAnd( + createTypeCheck(createIdentifier("define"), "function"), + createPropertyAccess(createIdentifier("define"), "amd") + ), + createBlock([ + createStatement( createCall( - createIdentifier("factory"), + createIdentifier("define"), /*typeArguments*/ undefined, [ - createIdentifier("require"), - createIdentifier("exports") + createArrayLiteral([ + createLiteral("require"), + createLiteral("exports"), + ...aliasedModuleNames, + ...unaliasedModuleNames + ]), + createIdentifier("factory") ] ) ) - ] - ), - setEmitFlags( - createIf( - createStrictInequality( - createIdentifier("v"), - createIdentifier("undefined") - ), - createStatement( - createAssignment( - createPropertyAccess(createIdentifier("module"), "exports"), - createIdentifier("v") - ) - ) - ), - EmitFlags.SingleLine + ]) ) - ]), - createIf( - createLogicalAnd( - createTypeCheck(createIdentifier("define"), "function"), - createPropertyAccess(createIdentifier("define"), "amd") - ), - createBlock([ - createStatement( - createCall( - createIdentifier("define"), - /*typeArguments*/ undefined, - [ - createArrayLiteral([ - createLiteral("require"), - createLiteral("exports"), - ...aliasedModuleNames, - ...unaliasedModuleNames - ]), - createIdentifier("factory") - ] - ) - ) - ]) ) - ) - ], - /*location*/ undefined, - /*multiLine*/ true + ], + /*multiLine*/ true + ), + /*location*/ undefined ) ); @@ -274,8 +278,8 @@ namespace ts { return updateSourceFileNode( node, - createNodeArray( - [ + setTextRange( + createNodeArray([ createStatement( createCall( umdHeader, @@ -300,7 +304,7 @@ namespace ts { ] ) ) - ], + ]), /*location*/ node.statements ) ); @@ -378,7 +382,7 @@ namespace ts { // Append the 'export =' statement if provided. addExportEqualsIfNeeded(statements, /*emitAsReturn*/ true); - const body = createBlock(statements, /*location*/ undefined, /*multiLine*/ true); + const body = createBlock(statements, /*multiLine*/ true); if (currentModuleInfo.hasExportStarsToExportValues) { // If we have any `export * from ...` declarations // we need to inform the emitter to add the __export helper. @@ -399,11 +403,8 @@ namespace ts { function addExportEqualsIfNeeded(statements: Statement[], emitAsReturn: boolean) { if (currentModuleInfo.exportEquals) { if (emitAsReturn) { - const statement = createReturn( - currentModuleInfo.exportEquals.expression, - /*location*/ currentModuleInfo.exportEquals - ); - + const statement = createReturn(currentModuleInfo.exportEquals.expression); + setTextRange(statement, currentModuleInfo.exportEquals); setEmitFlags(statement, EmitFlags.NoTokenSourceMaps | EmitFlags.NoComments); statements.push(statement); } @@ -415,10 +416,10 @@ namespace ts { "exports" ), currentModuleInfo.exportEquals.expression - ), - /*location*/ currentModuleInfo.exportEquals + ) ); + setTextRange(statement, currentModuleInfo.exportEquals); setEmitFlags(statement, EmitFlags.NoComments); statements.push(statement); } @@ -481,7 +482,7 @@ namespace ts { if (moduleKind !== ModuleKind.AMD) { if (!node.importClause) { // import "mod"; - return createStatement(createRequireCall(node), /*location*/ node); + return setTextRange(createStatement(createRequireCall(node)), node); } else { const variables: VariableDeclaration[] = []; @@ -520,12 +521,13 @@ namespace ts { } statements = append(statements, - createVariableStatement( - /*modifiers*/ undefined, - createVariableDeclarationList( - variables, - /*location*/ undefined, - languageVersion >= ScriptTarget.ES2015 ? NodeFlags.Const : NodeFlags.None + setTextRange( + createVariableStatement( + /*modifiers*/ undefined, + createVariableDeclarationList( + variables, + languageVersion >= ScriptTarget.ES2015 ? NodeFlags.Const : NodeFlags.None + ) ), /*location*/ node ) @@ -539,14 +541,15 @@ namespace ts { /*modifiers*/ undefined, createVariableDeclarationList( [ - createVariableDeclaration( - getSynthesizedClone(namespaceDeclaration.name), - /*type*/ undefined, - getGeneratedNameForNode(node), + setTextRange( + createVariableDeclaration( + getSynthesizedClone(namespaceDeclaration.name), + /*type*/ undefined, + getGeneratedNameForNode(node) + ), /*location*/ node ) ], - /*location*/ undefined, languageVersion >= ScriptTarget.ES2015 ? NodeFlags.Const : NodeFlags.None ) ) @@ -592,31 +595,34 @@ namespace ts { if (moduleKind !== ModuleKind.AMD) { if (hasModifier(node, ModifierFlags.Export)) { statements = append(statements, - createStatement( - createExportExpression( - node.name, - createRequireCall(node) + setTextRange( + createStatement( + createExportExpression( + node.name, + createRequireCall(node) + ) ), - /*location*/ node + node ) ); } else { statements = append(statements, - createVariableStatement( - /*modifiers*/ undefined, - createVariableDeclarationList( - [ - createVariableDeclaration( - getSynthesizedClone(node.name), - /*type*/ undefined, - createRequireCall(node) - ) - ], - /*location*/ undefined, - /*flags*/ languageVersion >= ScriptTarget.ES2015 ? NodeFlags.Const : NodeFlags.None + setTextRange( + createVariableStatement( + /*modifiers*/ undefined, + createVariableDeclarationList( + [ + createVariableDeclaration( + getSynthesizedClone(node.name), + /*type*/ undefined, + createRequireCall(node) + ) + ], + /*flags*/ languageVersion >= ScriptTarget.ES2015 ? NodeFlags.Const : NodeFlags.None + ) ), - /*location*/ node + node ) ); } @@ -624,9 +630,11 @@ namespace ts { else { if (hasModifier(node, ModifierFlags.Export)) { statements = append(statements, - createStatement( - createExportExpression(getExportName(node), getLocalName(node)), - /*location*/ node + setTextRange( + createStatement( + createExportExpression(getExportName(node), getLocalName(node)) + ), + node ) ); } @@ -662,15 +670,17 @@ namespace ts { // export { x, y } from "mod"; if (moduleKind !== ModuleKind.AMD) { statements.push( - createVariableStatement( - /*modifiers*/ undefined, - createVariableDeclarationList([ - createVariableDeclaration( - generatedName, - /*type*/ undefined, - createRequireCall(node) - ) - ]), + setTextRange( + createVariableStatement( + /*modifiers*/ undefined, + createVariableDeclarationList([ + createVariableDeclaration( + generatedName, + /*type*/ undefined, + createRequireCall(node) + ) + ]) + ), /*location*/ node ) ); @@ -681,9 +691,11 @@ namespace ts { specifier.propertyName || specifier.name ); statements.push( - createStatement( - createExportExpression(getExportName(specifier), exportedValue), - /*location*/ specifier + setTextRange( + createStatement( + createExportExpression(getExportName(specifier), exportedValue) + ), + specifier ) ); } @@ -692,17 +704,19 @@ namespace ts { } else { // export * from "mod"; - return createStatement( - createCall( - createIdentifier("__export"), - /*typeArguments*/ undefined, - [ - moduleKind !== ModuleKind.AMD - ? createRequireCall(node) - : generatedName - ] + return setTextRange( + createStatement( + createCall( + createIdentifier("__export"), + /*typeArguments*/ undefined, + [ + moduleKind !== ModuleKind.AMD + ? createRequireCall(node) + : generatedName + ] + ) ), - /*location*/ node + node ); } } @@ -741,15 +755,17 @@ namespace ts { if (hasModifier(node, ModifierFlags.Export)) { statements = append(statements, setOriginalNode( - createFunctionDeclaration( - /*decorators*/ undefined, - visitNodes(node.modifiers, modifierVisitor, isModifier), - node.asteriskToken, - getDeclarationName(node, /*allowComments*/ true, /*allowSourceMaps*/ true), - /*typeParameters*/ undefined, - node.parameters, - /*type*/ undefined, - node.body, + setTextRange( + createFunctionDeclaration( + /*decorators*/ undefined, + visitNodes(node.modifiers, modifierVisitor, isModifier), + node.asteriskToken, + getDeclarationName(node, /*allowComments*/ true, /*allowSourceMaps*/ true), + /*typeParameters*/ undefined, + node.parameters, + /*type*/ undefined, + node.body + ), /*location*/ node ), /*original*/ node @@ -782,16 +798,18 @@ namespace ts { if (hasModifier(node, ModifierFlags.Export)) { statements = append(statements, setOriginalNode( - createClassDeclaration( - /*decorators*/ undefined, - visitNodes(node.modifiers, modifierVisitor, isModifier), - getDeclarationName(node, /*allowComments*/ true, /*allowSourceMaps*/ true), - /*typeParameters*/ undefined, - node.heritageClauses, - node.members, - /*location*/ node + setTextRange( + createClassDeclaration( + /*decorators*/ undefined, + visitNodes(node.modifiers, modifierVisitor, isModifier), + getDeclarationName(node, /*allowComments*/ true, /*allowSourceMaps*/ true), + /*typeParameters*/ undefined, + node.heritageClauses, + node.members + ), + node ), - /*original*/ node + node ) ); } @@ -843,7 +861,7 @@ namespace ts { } if (expressions) { - statements = append(statements, createStatement(inlineExpressions(expressions), /*location*/ node)); + statements = append(statements, setTextRange(createStatement(inlineExpressions(expressions)), node)); } } else { @@ -880,9 +898,11 @@ namespace ts { } else { return createAssignment( - createPropertyAccess( - createIdentifier("exports"), - node.name, + setTextRange( + createPropertyAccess( + createIdentifier("exports"), + node.name + ), /*location*/ node.name ), node.initializer @@ -1115,7 +1135,7 @@ namespace ts { createStatement( createExportExpression( createIdentifier("__esModule"), - createLiteral(true) + createTrue() ) ) ); @@ -1130,7 +1150,7 @@ namespace ts { createIdentifier("exports"), createLiteral("__esModule"), createObjectLiteral([ - createPropertyAssignment("value", createLiteral(true)) + createPropertyAssignment("value", createTrue()) ]) ] ) @@ -1153,7 +1173,7 @@ namespace ts { * @param allowComments An optional value indicating whether to emit comments for the statement. */ function createExportStatement(name: Identifier, value: Expression, location?: TextRange, allowComments?: boolean) { - const statement = createStatement(createExportExpression(name, value), location); + const statement = setTextRange(createStatement(createExportExpression(name, value)), location); startOnNewLine(statement); if (!allowComments) { setEmitFlags(statement, EmitFlags.NoComments); @@ -1170,12 +1190,14 @@ namespace ts { * @param location The location to use for source maps and comments for the export. */ function createExportExpression(name: Identifier, value: Expression, location?: TextRange) { - return createAssignment( - createPropertyAccess( - createIdentifier("exports"), - getSynthesizedClone(name) + return setTextRange( + createAssignment( + createPropertyAccess( + createIdentifier("exports"), + getSynthesizedClone(name) + ), + value ), - value, location ); } @@ -1268,9 +1290,9 @@ namespace ts { // destructuring assignment if (node.objectAssignmentInitializer) { const initializer = createAssignment(exportedOrImportedName, node.objectAssignmentInitializer); - return createPropertyAssignment(name, initializer, /*location*/ node); + return setTextRange(createPropertyAssignment(name, initializer), node); } - return createPropertyAssignment(name, exportedOrImportedName, /*location*/ node); + return setTextRange(createPropertyAssignment(name, exportedOrImportedName), node); } return node; } @@ -1312,9 +1334,11 @@ namespace ts { if (!isGeneratedIdentifier(node) && !isLocalName(node)) { const exportContainer = resolver.getReferencedExportContainer(node, isExportName(node)); if (exportContainer && exportContainer.kind === SyntaxKind.SourceFile) { - return createPropertyAccess( - createIdentifier("exports"), - getSynthesizedClone(node), + return setTextRange( + createPropertyAccess( + createIdentifier("exports"), + getSynthesizedClone(node) + ), /*location*/ node ); } @@ -1322,17 +1346,21 @@ namespace ts { const importDeclaration = resolver.getReferencedImportDeclaration(node); if (importDeclaration) { if (isImportClause(importDeclaration)) { - return createPropertyAccess( - getGeneratedNameForNode(importDeclaration.parent), - createIdentifier("default"), + return setTextRange( + createPropertyAccess( + getGeneratedNameForNode(importDeclaration.parent), + createIdentifier("default") + ), /*location*/ node ); } else if (isImportSpecifier(importDeclaration)) { const name = importDeclaration.propertyName || importDeclaration.name; - return createPropertyAccess( - getGeneratedNameForNode(importDeclaration.parent.parent.parent), - getSynthesizedClone(name), + return setTextRange( + createPropertyAccess( + getGeneratedNameForNode(importDeclaration.parent.parent.parent), + getSynthesizedClone(name) + ), /*location*/ node ); } @@ -1400,10 +1428,12 @@ namespace ts { const exportedNames = getExports(node.operand); if (exportedNames) { let expression: Expression = node.kind === SyntaxKind.PostfixUnaryExpression - ? createBinary( - node.operand, - createToken(node.operator === SyntaxKind.PlusPlusToken ? SyntaxKind.PlusEqualsToken : SyntaxKind.MinusEqualsToken), - createLiteral(1), + ? setTextRange( + createBinary( + node.operand, + createToken(node.operator === SyntaxKind.PlusPlusToken ? SyntaxKind.PlusEqualsToken : SyntaxKind.MinusEqualsToken), + createLiteral(1) + ), /*location*/ node) : node; for (const exportName of exportedNames) { diff --git a/src/compiler/transformers/module/system.ts b/src/compiler/transformers/module/system.ts index 6c59ea194cb..b2999201504 100644 --- a/src/compiler/transformers/module/system.ts +++ b/src/compiler/transformers/module/system.ts @@ -105,17 +105,20 @@ namespace ts { const updated = setEmitFlags( updateSourceFileNode( node, - createNodeArray([ - createStatement( - createCall( - createPropertyAccess(createIdentifier("System"), "register"), - /*typeArguments*/ undefined, - moduleName - ? [moduleName, dependencies, moduleBodyFunction] - : [dependencies, moduleBodyFunction] + setTextRange( + createNodeArray([ + createStatement( + createCall( + createPropertyAccess(createIdentifier("System"), "register"), + /*typeArguments*/ undefined, + moduleName + ? [moduleName, dependencies, moduleBodyFunction] + : [dependencies, moduleBodyFunction] + ) ) - ) - ], node.statements) + ]), + node.statements + ) ), EmitFlags.NoTrailingComments); if (!(compilerOptions.outFile || compilerOptions.out)) { @@ -260,35 +263,26 @@ namespace ts { addRange(statements, endLexicalEnvironment()); const exportStarFunction = addExportStarIfNeeded(statements); - statements.push( - createReturn( - setMultiLine( - createObjectLiteral([ - createPropertyAssignment("setters", - createSettersArray(exportStarFunction, dependencyGroups) - ), - createPropertyAssignment("execute", - createFunctionExpression( - /*modifiers*/ undefined, - /*asteriskToken*/ undefined, - /*name*/ undefined, - /*typeParameters*/ undefined, - /*parameters*/ [], - /*type*/ undefined, - createBlock( - executeStatements, - /*location*/ undefined, - /*multiLine*/ true - ) - ) - ) - ]), - /*multiLine*/ true + const moduleObject = createObjectLiteral([ + createPropertyAssignment("setters", + createSettersArray(exportStarFunction, dependencyGroups) + ), + createPropertyAssignment("execute", + createFunctionExpression( + /*modifiers*/ undefined, + /*asteriskToken*/ undefined, + /*name*/ undefined, + /*typeParameters*/ undefined, + /*parameters*/ [], + /*type*/ undefined, + createBlock(executeStatements, /*multiLine*/ true) ) ) - ); + ]); - return createBlock(statements, /*location*/ undefined, /*multiLine*/ true); + moduleObject.multiLine = true; + statements.push(createReturn(moduleObject)); + return createBlock(statements, /*multiLine*/ true); } /** @@ -337,7 +331,7 @@ namespace ts { exportedNames.push( createPropertyAssignment( createLiteral(exportedLocalName), - createLiteral(true) + createTrue() ) ); } @@ -359,7 +353,7 @@ namespace ts { exportedNames.push( createPropertyAssignment( createLiteral((element.name || element.propertyName).text), - createLiteral(true) + createTrue() ) ); } @@ -373,7 +367,7 @@ namespace ts { createVariableDeclaration( exportedNamesStorageRef, /*type*/ undefined, - createObjectLiteral(exportedNames, /*location*/ undefined, /*multiline*/ true) + createObjectLiteral(exportedNames, /*multiline*/ true) ) ]) ) @@ -456,9 +450,7 @@ namespace ts { [exports] ) ) - ], - /*location*/ undefined, - /*multiline*/ true) + ], /*multiline*/ true) ); } @@ -525,7 +517,7 @@ namespace ts { createCall( exportFunction, /*typeArguments*/ undefined, - [createObjectLiteral(properties, /*location*/ undefined, /*multiline*/ true)] + [createObjectLiteral(properties, /*multiline*/ true)] ) ) ); @@ -558,12 +550,12 @@ namespace ts { /*typeParameters*/ undefined, [createParameter(/*decorators*/ undefined, /*modifiers*/ undefined, /*dotDotDotToken*/ undefined, parameterName)], /*type*/ undefined, - createBlock(statements, /*location*/ undefined, /*multiLine*/ true) + createBlock(statements, /*multiLine*/ true) ) ); } - return createArrayLiteral(setters, /*location*/ undefined, /*multiLine*/ true); + return createArrayLiteral(setters, /*multiLine*/ true); } // @@ -713,19 +705,23 @@ namespace ts { // Rewrite the class declaration into an assignment of a class expression. statements = append(statements, - createStatement( - createAssignment( - name, - createClassExpression( - /*modifiers*/ undefined, - node.name, - /*typeParameters*/ undefined, - visitNodes(node.heritageClauses, destructuringVisitor, isHeritageClause), - visitNodes(node.members, destructuringVisitor, isClassElement), - /*location*/ node + setTextRange( + createStatement( + createAssignment( + name, + setTextRange( + createClassExpression( + /*modifiers*/ undefined, + node.name, + /*typeParameters*/ undefined, + visitNodes(node.heritageClauses, destructuringVisitor, isHeritageClause), + visitNodes(node.members, destructuringVisitor, isClassElement) + ), + node + ) ) ), - /*location*/ node + node ) ); @@ -766,7 +762,7 @@ namespace ts { let statements: Statement[]; if (expressions) { - statements = append(statements, createStatement(inlineExpressions(expressions), /*location*/ node)); + statements = append(statements, setTextRange(createStatement(inlineExpressions(expressions)), node)); } if (isMarkedDeclaration) { @@ -864,8 +860,8 @@ namespace ts { function createVariableAssignment(name: Identifier, value: Expression, location: TextRange, isExportedDeclaration: boolean) { hoistVariableDeclaration(getSynthesizedClone(name)); return isExportedDeclaration - ? createExportExpression(name, preventSubstitution(createAssignment(name, value, location))) - : preventSubstitution(createAssignment(name, value, location)); + ? createExportExpression(name, preventSubstitution(setTextRange(createAssignment(name, value), location))) + : preventSubstitution(setTextRange(createAssignment(name, value), location)); } /** @@ -1642,16 +1638,20 @@ namespace ts { const importDeclaration = resolver.getReferencedImportDeclaration(node); if (importDeclaration) { if (isImportClause(importDeclaration)) { - return createPropertyAccess( - getGeneratedNameForNode(importDeclaration.parent), - createIdentifier("default"), + return setTextRange( + createPropertyAccess( + getGeneratedNameForNode(importDeclaration.parent), + createIdentifier("default") + ), /*location*/ node ); } else if (isImportSpecifier(importDeclaration)) { - return createPropertyAccess( - getGeneratedNameForNode(importDeclaration.parent.parent.parent), - getSynthesizedClone(importDeclaration.propertyName || importDeclaration.name), + return setTextRange( + createPropertyAccess( + getGeneratedNameForNode(importDeclaration.parent.parent.parent), + getSynthesizedClone(importDeclaration.propertyName || importDeclaration.name) + ), /*location*/ node ); } @@ -1718,10 +1718,13 @@ namespace ts { const exportedNames = getExports(node.operand); if (exportedNames) { let expression: Expression = node.kind === SyntaxKind.PostfixUnaryExpression - ? createPrefix( - node.operator, - node.operand, - /*location*/ node) + ? setTextRange( + createPrefix( + node.operator, + node.operand + ), + node + ) : node; for (const exportName of exportedNames) { diff --git a/src/compiler/transformers/ts.ts b/src/compiler/transformers/ts.ts index a61998e8af9..b18ab67381e 100644 --- a/src/compiler/transformers/ts.ts +++ b/src/compiler/transformers/ts.ts @@ -588,17 +588,17 @@ namespace ts { name, /*typeParameters*/ undefined, visitNodes(node.heritageClauses, visitor, isHeritageClause), - transformClassMembers(node, hasExtendsClause), - node); - - let emitFlags = getEmitFlags(node); + transformClassMembers(node, hasExtendsClause) + ); // To better align with the old emitter, we should not emit a trailing source map // entry if the class has static properties. + let emitFlags = getEmitFlags(node); if (hasStaticProperties) { emitFlags |= EmitFlags.NoTrailingSourceMap; } + setTextRange(classDeclaration, node); setOriginalNode(classDeclaration, node); setEmitFlags(classDeclaration, emitFlags); return classDeclaration; @@ -709,13 +709,24 @@ namespace ts { // } const heritageClauses = visitNodes(node.heritageClauses, visitor, isHeritageClause); const members = transformClassMembers(node, hasExtendsClause); - const classExpression = createClassExpression(/*modifiers*/ undefined, name, /*typeParameters*/ undefined, heritageClauses, members, location); + const classExpression = createClassExpression(/*modifiers*/ undefined, name, /*typeParameters*/ undefined, heritageClauses, members); setOriginalNode(classExpression, node); + setTextRange(classExpression, location); // let ${name} = ${classExpression} where name is either declaredName if the class doesn't contain self-reference // or decoratedClassAlias if the class contain self-reference. - const statement = createLetStatement(declName, classAlias ? createAssignment(classAlias, classExpression) : classExpression, location); + const statement = createVariableStatement( + /*modifiers*/ undefined, + createVariableDeclarationList([ + createVariableDeclaration( + declName, + /*type*/ undefined, + classAlias ? createAssignment(classAlias, classExpression) : classExpression + ) + ], NodeFlags.Let) + ); setOriginalNode(statement, node); + setTextRange(statement, location); setCommentRange(statement, node); return statement; } @@ -734,18 +745,17 @@ namespace ts { const heritageClauses = visitNodes(node.heritageClauses, visitor, isHeritageClause); const members = transformClassMembers(node, some(heritageClauses, c => c.token === SyntaxKind.ExtendsKeyword)); - const classExpression = setOriginalNode( - createClassExpression( - /*modifiers*/ undefined, - node.name, - /*typeParameters*/ undefined, - heritageClauses, - members, - /*location*/ node - ), - node + const classExpression = createClassExpression( + /*modifiers*/ undefined, + node.name, + /*typeParameters*/ undefined, + heritageClauses, + members ); + setOriginalNode(classExpression, node); + setTextRange(classExpression, node); + if (staticProperties.length > 0) { const expressions: Expression[] = []; const temp = createTempVariable(hoistVariableDeclaration); @@ -781,7 +791,7 @@ namespace ts { } addRange(members, visitNodes(node.members, classElementVisitor, isClassElement)); - return createNodeArray(members, /*location*/ node.members); + return setTextRange(createNodeArray(members), /*location*/ node.members); } /** @@ -812,12 +822,14 @@ namespace ts { // } return startOnNewLine( setOriginalNode( - createConstructor( - /*decorators*/ undefined, - /*modifiers*/ undefined, - parameters, - body, - /*location*/ constructor || node + setTextRange( + createConstructor( + /*decorators*/ undefined, + /*modifiers*/ undefined, + parameters, + body + ), + constructor || node ), constructor ) @@ -919,13 +931,15 @@ namespace ts { // End the lexical environment. addRange(statements, endLexicalEnvironment()); - return createBlock( - createNodeArray( - statements, - /*location*/ constructor ? constructor.body.statements : node.members + return setTextRange( + createBlock( + setTextRange( + createNodeArray(statements), + /*location*/ constructor ? constructor.body.statements : node.members + ), + /*multiLine*/ true ), - /*location*/ constructor ? constructor.body : /*location*/ undefined, - /*multiLine*/ true + /*location*/ constructor ? constructor.body : undefined ); } @@ -991,16 +1005,20 @@ namespace ts { setEmitFlags(localName, EmitFlags.NoComments); return startOnNewLine( - createStatement( - createAssignment( - createPropertyAccess( - createThis(), - propertyName, - /*location*/ node.name - ), - localName + setTextRange( + createStatement( + createAssignment( + setTextRange( + createPropertyAccess( + createThis(), + propertyName + ), + node.name + ), + localName + ) ), - /*location*/ moveRangePos(node, -1) + moveRangePos(node, -1) ) ); } @@ -1504,7 +1522,7 @@ namespace ts { (properties || (properties = [])).push(createPropertyAssignment("returnType", createArrowFunction(/*modifiers*/ undefined, /*typeParameters*/ undefined, [], /*type*/ undefined, createToken(SyntaxKind.EqualsGreaterThanToken), serializeReturnTypeOfNode(node)))); } if (properties) { - decoratorExpressions.push(createMetadataHelper(context, "design:typeinfo", createObjectLiteral(properties, /*location*/ undefined, /*multiLine*/ true))); + decoratorExpressions.push(createMetadataHelper(context, "design:typeinfo", createObjectLiteral(properties, /*multiLine*/ true))); } } } @@ -1939,10 +1957,7 @@ namespace ts { expression = createAssignment(generatedName, expression); } - return setOriginalNode( - createComputedPropertyName(expression, /*location*/ name), - name - ); + return updateComputedPropertyName(name, expression); } else { return name; @@ -1961,9 +1976,11 @@ namespace ts { function visitHeritageClause(node: HeritageClause): HeritageClause { if (node.token === SyntaxKind.ExtendsKeyword) { const types = visitNodes(node.types, visitor, isExpressionWithTypeArguments, 0, 1); - return createHeritageClause( - SyntaxKind.ExtendsKeyword, - types, + return setTextRange( + createHeritageClause( + SyntaxKind.ExtendsKeyword, + types + ), node ); } @@ -1980,11 +1997,10 @@ namespace ts { * @param node The ExpressionWithTypeArguments to transform. */ function visitExpressionWithTypeArguments(node: ExpressionWithTypeArguments): ExpressionWithTypeArguments { - const expression = visitNode(node.expression, visitor, isLeftHandSideExpression); - return createExpressionWithTypeArguments( + return updateExpressionWithTypeArguments( + node, /*typeArguments*/ undefined, - expression, - node + visitNode(node.expression, visitor, isLeftHandSideExpression) ); } @@ -2205,13 +2221,13 @@ namespace ts { visitNode(node.name, visitor, isBindingName), /*questionToken*/ undefined, /*type*/ undefined, - visitNode(node.initializer, visitor, isExpression), - /*location*/ moveRangePastModifiers(node) + visitNode(node.initializer, visitor, isExpression) ); // While we emit the source map for the node after skipping decorators and modifiers, // we need to emit the comments for the original range. setOriginalNode(parameter, node); + setTextRange(parameter, moveRangePastModifiers(node)); setCommentRange(parameter, node); setSourceMapRange(parameter, moveRangePastModifiers(node)); setEmitFlags(parameter.name, EmitFlags.NoTrailingSourceMap); @@ -2233,11 +2249,13 @@ namespace ts { return undefined; } - return createStatement( - inlineExpressions( - map(variables, transformInitializedVariable) + return setTextRange( + createStatement( + inlineExpressions( + map(variables, transformInitializedVariable) + ) ), - /*location*/ node + node ); } else { @@ -2258,9 +2276,11 @@ namespace ts { ); } else { - return createAssignment( - getNamespaceMemberNameWithSourceMapsAndWithoutComments(name), - visitNode(node.initializer, visitor, isExpression), + return setTextRange( + createAssignment( + getNamespaceMemberNameWithSourceMapsAndWithoutComments(name), + visitNode(node.initializer, visitor, isExpression) + ), /*location*/ node ); } @@ -2418,11 +2438,11 @@ namespace ts { ), /*typeArguments*/ undefined, [moduleArg] - ), - /*location*/ node + ) ); setOriginalNode(enumStatement, node); + setTextRange(enumStatement, node); setEmitFlags(enumStatement, emitFlags); statements.push(enumStatement); @@ -2448,8 +2468,7 @@ namespace ts { currentNamespaceContainerName = savedCurrentNamespaceLocalName; return createBlock( - createNodeArray(statements, /*location*/ node.members), - /*location*/ undefined, + setTextRange(createNodeArray(statements), /*location*/ node.members), /*multiLine*/ true ); } @@ -2464,22 +2483,26 @@ namespace ts { // we pass false as 'generateNameForComputedPropertyName' for a backward compatibility purposes // old emitter always generate 'expression' part of the name as-is. const name = getExpressionForPropertyName(member, /*generateNameForComputedPropertyName*/ false); - return createStatement( - createAssignment( - createElementAccess( - currentNamespaceContainerName, + return setTextRange( + createStatement( + setTextRange( createAssignment( createElementAccess( currentNamespaceContainerName, - name + createAssignment( + createElementAccess( + currentNamespaceContainerName, + name + ), + transformEnumMemberDeclarationValue(member) + ) ), - transformEnumMemberDeclarationValue(member) - ) - ), - name, - /*location*/ member + name + ), + member + ) ), - /*location*/ member + member ); } @@ -2697,11 +2720,11 @@ namespace ts { ), /*typeArguments*/ undefined, [moduleArg] - ), - /*location*/ node + ) ); setOriginalNode(moduleStatement, node); + setTextRange(moduleStatement, node); setEmitFlags(moduleStatement, emitFlags); statements.push(moduleStatement); @@ -2756,13 +2779,13 @@ namespace ts { currentScopeFirstDeclarationsOfName = savedCurrentScopeFirstDeclarationsOfName; const block = createBlock( - createNodeArray( - statements, + setTextRange( + createNodeArray(statements), /*location*/ statementsLocation ), - /*location*/ blockLocation, /*multiLine*/ true ); + setTextRange(block, blockLocation); // namespace hello.hi.world { // function foo() {} @@ -2962,18 +2985,20 @@ namespace ts { // export var ${name} = ${moduleReference}; // var ${name} = ${moduleReference}; return setOriginalNode( - createVariableStatement( - visitNodes(node.modifiers, modifierVisitor, isModifier), - createVariableDeclarationList([ - setOriginalNode( - createVariableDeclaration( - node.name, - /*type*/ undefined, - moduleReference - ), - node - ) - ]), + setTextRange( + createVariableStatement( + visitNodes(node.modifiers, modifierVisitor, isModifier), + createVariableDeclarationList([ + setOriginalNode( + createVariableDeclaration( + node.name, + /*type*/ undefined, + moduleReference + ), + node + ) + ]) + ), node ), node @@ -3034,7 +3059,7 @@ namespace ts { * Creates a statement for the provided expression. This is used in calls to `map`. */ function expressionToStatement(expression: Expression) { - return createStatement(expression, /*location*/ undefined); + return createStatement(expression); } function addExportMemberAssignment(statements: Statement[], node: ClassDeclaration | FunctionDeclaration) { @@ -3050,17 +3075,19 @@ namespace ts { } function createNamespaceExport(exportName: Identifier, exportValue: Expression, location?: TextRange) { - return createStatement( - createAssignment( - getNamespaceMemberName(currentNamespaceContainerName, exportName, /*allowComments*/ false, /*allowSourceMaps*/ true), - exportValue + return setTextRange( + createStatement( + createAssignment( + getNamespaceMemberName(currentNamespaceContainerName, exportName, /*allowComments*/ false, /*allowSourceMaps*/ true), + exportValue + ) ), location ); } function createNamespaceExportExpression(exportName: Identifier, exportValue: Expression, location?: TextRange) { - return createAssignment(getNamespaceMemberNameWithSourceMapsAndWithoutComments(exportName), exportValue, location); + return setTextRange(createAssignment(getNamespaceMemberNameWithSourceMapsAndWithoutComments(exportName), exportValue), location); } function getNamespaceMemberNameWithSourceMapsAndWithoutComments(name: Identifier) { @@ -3201,9 +3228,9 @@ namespace ts { // destructuring assignment if (node.objectAssignmentInitializer) { const initializer = createAssignment(exportedName, node.objectAssignmentInitializer); - return createPropertyAssignment(name, initializer, /*location*/ node); + return setTextRange(createPropertyAssignment(name, initializer), node); } - return createPropertyAssignment(name, exportedName, /*location*/ node); + return setTextRange(createPropertyAssignment(name, exportedName), node); } } return node; @@ -3263,7 +3290,10 @@ namespace ts { (applicableSubstitutions & TypeScriptSubstitutionFlags.NamespaceExports && container.kind === SyntaxKind.ModuleDeclaration) || (applicableSubstitutions & TypeScriptSubstitutionFlags.NonQualifiedEnumMembers && container.kind === SyntaxKind.EnumDeclaration); if (substitute) { - return createPropertyAccess(getGeneratedNameForNode(container), node, /*location*/ node); + return setTextRange( + createPropertyAccess(getGeneratedNameForNode(container), node), + /*location*/ node + ); } } } @@ -3322,13 +3352,15 @@ namespace ts { function createParamHelper(context: TransformationContext, expression: Expression, parameterOffset: number, location?: TextRange) { context.requestEmitHelper(paramHelper); - return createCall( - getHelperName("__param"), - /*typeArguments*/ undefined, - [ - createLiteral(parameterOffset), - expression - ], + return setTextRange( + createCall( + getHelperName("__param"), + /*typeArguments*/ undefined, + [ + createLiteral(parameterOffset), + expression + ] + ), location ); } @@ -3371,7 +3403,7 @@ namespace ts { function createDecorateHelper(context: TransformationContext, decoratorExpressions: Expression[], target: Expression, memberName?: Expression, descriptor?: Expression, location?: TextRange) { context.requestEmitHelper(decorateHelper); const argumentsArray: Expression[] = []; - argumentsArray.push(createArrayLiteral(decoratorExpressions, /*location*/ undefined, /*multiLine*/ true)); + argumentsArray.push(createArrayLiteral(decoratorExpressions, /*multiLine*/ true)); argumentsArray.push(target); if (memberName) { argumentsArray.push(memberName); @@ -3380,6 +3412,13 @@ namespace ts { } } - return createCall(getHelperName("__decorate"), /*typeArguments*/ undefined, argumentsArray, location); + return setTextRange( + createCall( + getHelperName("__decorate"), + /*typeArguments*/ undefined, + argumentsArray + ), + location + ); } } diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 8660e6138cd..ae678f429f1 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -958,8 +958,7 @@ } // Represents an expression that is elided as part of a transformation to emit comments on a - // not-emitted node. The 'expression' property of a NotEmittedExpression should be emitted. - // @internal + // not-emitted node. The 'expression' property of a PartiallyEmittedExpression should be emitted. export interface PartiallyEmittedExpression extends LeftHandSideExpression { kind: SyntaxKind.PartiallyEmittedExpression; expression: Expression; @@ -1538,7 +1537,6 @@ // Represents a statement that is elided as part of a transformation to emit comments on a // not-emitted node. - // @internal export interface NotEmittedStatement extends Statement { kind: SyntaxKind.NotEmittedStatement; } @@ -3730,7 +3728,6 @@ helpers?: EmitHelper[]; // Emit helpers for the node } - /* @internal */ export const enum EmitFlags { SingleLine = 1 << 0, // The contents of this node should be emitted on a single line. AdviseOnEmitNode = 1 << 1, // The printer should invoke the onEmitNode callback when printing this node. @@ -3759,7 +3756,6 @@ HasEndOfDeclarationMarker = 1 << 21, // Declaration has an associated NotEmittedStatement to mark the end of the declaration } - /* @internal */ export interface EmitHelper { readonly name: string; // A unique name for this helper. readonly scoped: boolean; // Indicates whether ther helper MUST be emitted in the current scope. diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index 01cfcb08047..6004bee466a 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -3331,6 +3331,14 @@ namespace ts { } } + export function getRangePos(range: TextRange | undefined) { + return range ? range.pos : -1; + } + + export function getRangeEnd(range: TextRange | undefined) { + return range ? range.end : -1; + } + /** * Increases (or decreases) a position by the provided amount. * diff --git a/src/compiler/visitor.ts b/src/compiler/visitor.ts index f3efc040e35..b6e0adc1294 100644 --- a/src/compiler/visitor.ts +++ b/src/compiler/visitor.ts @@ -627,8 +627,7 @@ namespace ts { // If we are not visiting all of the original nodes, we must always create a new array. // Since this is a fragment of a node array, we do not copy over the previous location // and will only copy over `hasTrailingComma` if we are including the last element. - updated = createNodeArray([], /*location*/ undefined, - /*hasTrailingComma*/ nodes.hasTrailingComma && start + count === length); + updated = createNodeArray([], /*hasTrailingComma*/ nodes.hasTrailingComma && start + count === length); } // Visit each original node. @@ -639,7 +638,8 @@ namespace ts { if (updated !== undefined || visited === undefined || visited !== node) { if (updated === undefined) { // Ensure we have a copy of `nodes`, up to the current index. - updated = createNodeArray(nodes.slice(0, i), /*location*/ nodes, nodes.hasTrailingComma); + updated = createNodeArray(nodes.slice(0, i), nodes.hasTrailingComma); + setTextRange(updated, nodes); } if (visited) { if (isArray(visited)) { @@ -675,10 +675,10 @@ namespace ts { context.startLexicalEnvironment(); statements = visitNodes(statements, visitor, isStatement, start); if (ensureUseStrict && !startsWithUseStrict(statements)) { - statements = createNodeArray([createStatement(createLiteral("use strict")), ...statements], statements); + statements = setTextRange(createNodeArray([createStatement(createLiteral("use strict")), ...statements]), statements); } const declarations = context.endLexicalEnvironment(); - return createNodeArray(concatenate(statements, declarations), statements); + return setTextRange(createNodeArray(concatenate(statements, declarations)), statements); } /** @@ -1228,7 +1228,7 @@ namespace ts { return statements; } return isNodeArray(statements) - ? createNodeArray(concatenate(statements, declarations), statements) + ? setTextRange(createNodeArray(concatenate(statements, declarations)), statements) : addRange(statements, declarations); } @@ -1252,13 +1252,19 @@ namespace ts { export function mergeFunctionBodyLexicalEnvironment(body: ConciseBody, declarations: Statement[]): ConciseBody { if (body && declarations !== undefined && declarations.length > 0) { if (isBlock(body)) { - return updateBlock(body, createNodeArray(concatenate(body.statements, declarations), body.statements)); + return updateBlock(body, setTextRange(createNodeArray(concatenate(body.statements, declarations)), body.statements)); } else { - return createBlock( - createNodeArray([createReturn(body, /*location*/ body), ...declarations], body), - /*location*/ body, - /*multiLine*/ true); + return setTextRange( + createBlock( + setTextRange( + createNodeArray([setTextRange(createReturn(body), body), ...declarations]), + body + ), + /*multiLine*/ true + ), + /*location*/ body + ); } } return body; From a72abc8ebc5c4c76122126b2212449fafa1277db Mon Sep 17 00:00:00 2001 From: Ron Buckton Date: Wed, 1 Feb 2017 19:41:28 -0800 Subject: [PATCH 30/58] Make getOriginalNode/getParseTreeNode public --- src/compiler/utilities.ts | 102 +++++++++++++++++++------------------- 1 file changed, 51 insertions(+), 51 deletions(-) diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index 6004bee466a..66efce4fef8 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -2042,57 +2042,6 @@ namespace ts { || positionIsSynthesized(node.end); } - export function getOriginalNode(node: Node): Node; - export function getOriginalNode(node: Node, nodeTest: (node: Node) => node is T): T; - export function getOriginalNode(node: Node, nodeTest?: (node: Node) => boolean): Node { - if (node) { - while (node.original !== undefined) { - node = node.original; - } - } - - return !nodeTest || nodeTest(node) ? node : undefined; - } - - /** - * Gets a value indicating whether a node originated in the parse tree. - * - * @param node The node to test. - */ - export function isParseTreeNode(node: Node): boolean { - return (node.flags & NodeFlags.Synthesized) === 0; - } - - /** - * Gets the original parse tree node for a node. - * - * @param node The original node. - * @returns The original parse tree node if found; otherwise, undefined. - */ - export function getParseTreeNode(node: Node): Node; - - /** - * Gets the original parse tree node for a node. - * - * @param node The original node. - * @param nodeTest A callback used to ensure the correct type of parse tree node is returned. - * @returns The original parse tree node if found; otherwise, undefined. - */ - export function getParseTreeNode(node: Node, nodeTest?: (node: Node) => node is T): T; - export function getParseTreeNode(node: Node, nodeTest?: (node: Node) => boolean): Node { - if (isParseTreeNode(node)) { - return node; - } - - node = getOriginalNode(node); - - if (isParseTreeNode(node) && (!nodeTest || nodeTest(node))) { - return node; - } - - return undefined; - } - export function getOriginalSourceFileOrBundle(sourceFileOrBundle: SourceFile | Bundle) { if (sourceFileOrBundle.kind === SyntaxKind.Bundle) { return updateBundle(sourceFileOrBundle, sameMap(sourceFileOrBundle.sourceFiles, getOriginalSourceFile)); @@ -4530,4 +4479,55 @@ namespace ts { return true; } } + + export function getOriginalNode(node: Node): Node; + export function getOriginalNode(node: Node, nodeTest: (node: Node) => node is T): T; + export function getOriginalNode(node: Node, nodeTest?: (node: Node) => boolean): Node { + if (node) { + while (node.original !== undefined) { + node = node.original; + } + } + + return !nodeTest || nodeTest(node) ? node : undefined; + } + + /** + * Gets a value indicating whether a node originated in the parse tree. + * + * @param node The node to test. + */ + export function isParseTreeNode(node: Node): boolean { + return (node.flags & NodeFlags.Synthesized) === 0; + } + + /** + * Gets the original parse tree node for a node. + * + * @param node The original node. + * @returns The original parse tree node if found; otherwise, undefined. + */ + export function getParseTreeNode(node: Node): Node; + + /** + * Gets the original parse tree node for a node. + * + * @param node The original node. + * @param nodeTest A callback used to ensure the correct type of parse tree node is returned. + * @returns The original parse tree node if found; otherwise, undefined. + */ + export function getParseTreeNode(node: Node, nodeTest?: (node: Node) => node is T): T; + export function getParseTreeNode(node: Node, nodeTest?: (node: Node) => boolean): Node { + if (isParseTreeNode(node)) { + return node; + } + + node = getOriginalNode(node); + + if (isParseTreeNode(node) && (!nodeTest || nodeTest(node))) { + return node; + } + + return undefined; + } } From 1f92bacdc81e7ae6706ad8776121e1db986a8b27 Mon Sep 17 00:00:00 2001 From: Mohamed Hegazy Date: Wed, 1 Feb 2017 22:08:08 -0800 Subject: [PATCH 31/58] Update AUTHORS for release-2.2 --- .mailmap | 14 +++++++++++++- AUTHORS.md | 12 ++++++++++++ 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/.mailmap b/.mailmap index ede478c8a18..6a9362f6e4c 100644 --- a/.mailmap +++ b/.mailmap @@ -8,11 +8,14 @@ Alexander Rusakov Alex Eagle Anatoly Ressin Anders Hejlsberg unknown unknown +about-code # Andreas Martin Andrej Baran +Andrew Ochsner Andrew Z Allen Andy Hanson Andy Anil Anar Anton Tolmachev +Anubha Mathur anubmat Arnavion # Arnav Singh Arthur Ozga Arthur Ozga Arthur Ozga Arthur Ozga Arthur Ozga Asad Saeeduddin @@ -37,6 +40,7 @@ Dan Corder Dan Quirk Dan Quirk nknown Daniel Rosenwasser Daniel Rosenwasser Daniel Rosenwasser Daniel Rosenwasser Daniel Rosenwasser David Li +David Sheldrick David Souther Denis Nedelyaev Dick van den Brink unknown unknown @@ -52,6 +56,7 @@ Evan Sebastian Eyas # Eyas Sharaiha Fabian Cook falsandtru # @falsandtru +flowmemo # @flowmemo Frank Wallis František Žiacik František Žiacik Gabe Moothart @@ -62,6 +67,7 @@ Graeme Wicksted Guillaume Salles Guy Bedford guybedford Harald Niesche +Homa Wong Iain Monro Ingvar Stepanyan impinball # Isiah Meadows @@ -81,6 +87,7 @@ Jonathan Park Jonathan Turner Jonathan Turner Jonathan Toland Jesse Schalken +Joel Day Josh Abernathy joshaber Josh Kalderimis Josh Soref @@ -95,10 +102,12 @@ Kanchalai Tanglertsampan Yui T Kanchalai Tanglertsampan Yui Kanchalai Tanglertsampan Yui Kanchalai Tanglertsampan yui T +Kārlis Gaņģis Keith Mashinter kmashint Ken Howard Kevin Lang kimamula # Kenji Imamula +Klaus Meinhardt Kyle Kelley Lorant Pinter Lucien Greathouse @@ -107,6 +116,7 @@ Martin Vseticka Martin Všeticka # Marin Marinov vvakame # Masahiro Wakame Matt McCutchen +MANISH-GIRI # Manish Giri Max Deepfield Micah Zoltu Michael @@ -213,4 +223,6 @@ Tim Perry Vidar Tonaas Fauske Viktor Zozulyak rix # Richard Sentino -rohitverma007 # Rohit Verma \ No newline at end of file +rohitverma007 # Rohit Verma +rdosanjh # Raj Dosanjh +gdh1995 # Dahan Gong \ No newline at end of file diff --git a/AUTHORS.md b/AUTHORS.md index ae7832176ea..196f5e84542 100644 --- a/AUTHORS.md +++ b/AUTHORS.md @@ -12,13 +12,16 @@ TypeScript is authored by: * Aliaksandr Radzivanovich * Anatoly Ressin * Anders Hejlsberg +* Andreas Martin * Andrej Baran +* Andrew Ochsner * Andrew Z Allen * András Parditka * Andy Hanson * Anil Anar * Anton Khlynovskiy * Anton Tolmachev +* Anubha Mathur * Arnav Singh * Arthur Ozga * Asad Saeeduddin @@ -42,12 +45,14 @@ TypeScript is authored by: * Cotton Hou * Cyrus Najmabadi * Dafrok Zhang +* Dahan Gong * Dan Corder * Dan Quirk * Daniel Hollocher * Daniel Rosenwasser * David Kmenta * David Li +* David Sheldrick * David Souther * Denis Nedelyaev * Dick van den Brink @@ -66,6 +71,7 @@ TypeScript is authored by: * Eyas Sharaiha * Fabian Cook * @falsandtru +* @flowmemo * Frank Wallis * Franklin Tse * František Žiacik @@ -79,6 +85,7 @@ TypeScript is authored by: * Guy Bedford * Harald Niesche * Herrington Darkholme +* Homa Wong * Iain Monro * Ingvar Stepanyan * Isiah Meadows @@ -93,6 +100,7 @@ TypeScript is authored by: * Jeffrey Morlan * Jesse Schalken * Jiri Tobisek +* Joel Day * Joey Wilson * Johannes Rieken * John Vilk @@ -114,10 +122,13 @@ TypeScript is authored by: * Ken Howard * Kenji Imamula * Kevin Lang +* Klaus Meinhardt * Kyle Kelley +* Kārlis Gaņģis * Lorant Pinter * Lucien Greathouse * Lukas Elmer +* Manish Giri * Marin Marinov * Marius Schulz * Martin Vseticka @@ -155,6 +166,7 @@ TypeScript is authored by: * @progre * Punya Biswal * Rado Kirov +* Raj Dosanjh * Richard Knoll * Richard Sentino * Robert Coie From 6c56b3d957d43dd180f72f6f4af430c10da6c2e7 Mon Sep 17 00:00:00 2001 From: Zhengbo Li Date: Thu, 2 Feb 2017 02:17:49 -0800 Subject: [PATCH 32/58] Fix casing in import quick fix --- src/services/codefixes/importFixes.ts | 31 +++++++------------ .../importNameCodeFixNewImportFile1.ts | 4 +-- 2 files changed, 14 insertions(+), 21 deletions(-) diff --git a/src/services/codefixes/importFixes.ts b/src/services/codefixes/importFixes.ts index 49b8526a1e0..3642e46612c 100644 --- a/src/services/codefixes/importFixes.ts +++ b/src/services/codefixes/importFixes.ts @@ -416,8 +416,8 @@ namespace ts.codefix { ); function getModuleSpecifierForNewImport() { - const fileName = sourceFile.path; - const moduleFileName = moduleSymbol.valueDeclaration.getSourceFile().path; + const fileName = sourceFile.fileName; + const moduleFileName = moduleSymbol.valueDeclaration.getSourceFile().fileName; const sourceDirectory = getDirectoryPath(fileName); const options = context.program.getCompilerOptions(); @@ -439,8 +439,7 @@ namespace ts.codefix { return undefined; } - const normalizedBaseUrl = toPath(options.baseUrl, getDirectoryPath(options.baseUrl), getCanonicalFileName); - let relativeName = tryRemoveParentDirectoryName(moduleFileName, normalizedBaseUrl); + let relativeName = getRelativePathIfInDirectory(moduleFileName, options.baseUrl); if (!relativeName) { return undefined; } @@ -477,9 +476,8 @@ namespace ts.codefix { function tryGetModuleNameFromRootDirs() { if (options.rootDirs) { - const normalizedRootDirs = map(options.rootDirs, rootDir => toPath(rootDir, /*basePath*/ undefined, getCanonicalFileName)); - const normalizedTargetPath = getPathRelativeToRootDirs(moduleFileName, normalizedRootDirs); - const normalizedSourcePath = getPathRelativeToRootDirs(sourceDirectory, normalizedRootDirs); + const normalizedTargetPath = getPathRelativeToRootDirs(moduleFileName, options.rootDirs); + const normalizedSourcePath = getPathRelativeToRootDirs(sourceDirectory, options.rootDirs); if (normalizedTargetPath !== undefined) { const relativePath = normalizedSourcePath !== undefined ? getRelativePath(normalizedTargetPath, normalizedSourcePath) : normalizedTargetPath; return removeFileExtension(relativePath); @@ -546,9 +544,9 @@ namespace ts.codefix { } } - function getPathRelativeToRootDirs(path: Path, rootDirs: Path[]) { + function getPathRelativeToRootDirs(path: string, rootDirs: string[]) { for (const rootDir of rootDirs) { - const relativeName = tryRemoveParentDirectoryName(path, rootDir); + const relativeName = getRelativePathIfInDirectory(path, rootDir); if (relativeName !== undefined) { return relativeName; } @@ -564,20 +562,15 @@ namespace ts.codefix { return fileName; } + function getRelativePathIfInDirectory(path: string, directoryPath: string) { + const relativePath = getRelativePathToDirectoryOrUrl(directoryPath, path, directoryPath, getCanonicalFileName, false); + return isRootedDiskPath(relativePath) || startsWith(relativePath, "..") ? undefined : relativePath; + } + function getRelativePath(path: string, directoryPath: string) { const relativePath = getRelativePathToDirectoryOrUrl(directoryPath, path, directoryPath, getCanonicalFileName, false); return moduleHasNonRelativeName(relativePath) ? "./" + relativePath : relativePath; } - - function tryRemoveParentDirectoryName(path: Path, parentDirectory: Path) { - const index = path.indexOf(parentDirectory); - if (index === 0) { - return endsWith(parentDirectory, directorySeparator) - ? path.substring(parentDirectory.length) - : path.substring(parentDirectory.length + 1); - } - return undefined; - } } } diff --git a/tests/cases/fourslash/importNameCodeFixNewImportFile1.ts b/tests/cases/fourslash/importNameCodeFixNewImportFile1.ts index 0223d96e018..9f6cac0b7c1 100644 --- a/tests/cases/fourslash/importNameCodeFixNewImportFile1.ts +++ b/tests/cases/fourslash/importNameCodeFixNewImportFile1.ts @@ -3,7 +3,7 @@ //// [|/// //// f1/*0*/();|] -// @Filename: module.ts +// @Filename: Module.ts //// export function f1() {} //// export var v1 = 5; @@ -12,7 +12,7 @@ verify.importFixAtPosition([ `/// -import { f1 } from "./module"; +import { f1 } from "./Module"; f1();` ]); \ No newline at end of file From 2f49eeca26a228ce9f9bce849198d1a2c2efc182 Mon Sep 17 00:00:00 2001 From: Andy Hanson Date: Thu, 2 Feb 2017 08:29:00 -0800 Subject: [PATCH 33/58] Remove useless test file --- tests/cases/fourslash/goToDefinitionFoo.ts | 6 ------ 1 file changed, 6 deletions(-) delete mode 100644 tests/cases/fourslash/goToDefinitionFoo.ts diff --git a/tests/cases/fourslash/goToDefinitionFoo.ts b/tests/cases/fourslash/goToDefinitionFoo.ts deleted file mode 100644 index 3e05ee20ecb..00000000000 --- a/tests/cases/fourslash/goToDefinitionFoo.ts +++ /dev/null @@ -1,6 +0,0 @@ -/// - -////function /*def*/f() {} -/////*use*/f(123); - -verify.goToDefinition("use", "def"); From 62f716aaa60ee39b696a2adeb582ec3f06ea72ea Mon Sep 17 00:00:00 2001 From: zhengbli Date: Thu, 2 Feb 2017 13:50:34 -0800 Subject: [PATCH 34/58] avoid removing comments when removing unused locals --- .../codefixes/unusedIdentifierFixes.ts | 48 ++++++++++++------- .../fourslash/unusedFunctionInNamespace1.ts | 2 + tests/cases/fourslash/unusedImports3FS.ts | 4 +- 3 files changed, 36 insertions(+), 18 deletions(-) diff --git a/src/services/codefixes/unusedIdentifierFixes.ts b/src/services/codefixes/unusedIdentifierFixes.ts index 2784a09a504..0ca01a81eb1 100644 --- a/src/services/codefixes/unusedIdentifierFixes.ts +++ b/src/services/codefixes/unusedIdentifierFixes.ts @@ -25,7 +25,7 @@ namespace ts.codefix { const forStatement = token.parent.parent.parent; const forInitializer = forStatement.initializer; if (forInitializer.declarations.length === 1) { - return createCodeFix("", forInitializer.pos, forInitializer.end - forInitializer.pos); + return createCodeFixToRemoveNode(forInitializer); } else { return removeSingleItem(forInitializer.declarations, token); @@ -35,7 +35,7 @@ namespace ts.codefix { const forOfStatement = token.parent.parent.parent; if (forOfStatement.initializer.kind === SyntaxKind.VariableDeclarationList) { const forOfInitializer = forOfStatement.initializer; - return createCodeFix("{}", forOfInitializer.declarations[0].pos, forOfInitializer.declarations[0].end - forOfInitializer.declarations[0].pos); + return createCodeFix("{}", forOfInitializer.declarations[0].getStart(), forOfInitializer.declarations[0].getWidth()); } break; @@ -47,12 +47,12 @@ namespace ts.codefix { case SyntaxKind.CatchClause: const catchClause = token.parent.parent; const parameter = catchClause.variableDeclaration.getChildren()[0]; - return createCodeFix("", parameter.pos, parameter.end - parameter.pos); + return createCodeFixToRemoveNode(parameter); default: const variableStatement = token.parent.parent.parent; if (variableStatement.declarationList.declarations.length === 1) { - return createCodeFix("", variableStatement.pos, variableStatement.end - variableStatement.pos); + return createCodeFixToRemoveNode(variableStatement); } else { const declarations = variableStatement.declarationList.declarations; @@ -72,7 +72,7 @@ namespace ts.codefix { case ts.SyntaxKind.Parameter: const functionDeclaration = token.parent.parent; if (functionDeclaration.parameters.length === 1) { - return createCodeFix("", token.parent.pos, token.parent.end - token.parent.pos); + return createCodeFixToRemoveNode(token.parent); } else { return removeSingleItem(functionDeclaration.parameters, token); @@ -81,14 +81,14 @@ namespace ts.codefix { // handle case where 'import a = A;' case SyntaxKind.ImportEqualsDeclaration: const importEquals = findImportDeclaration(token); - return createCodeFix("", importEquals.pos, importEquals.end - importEquals.pos); + return createCodeFixToRemoveNode(importEquals); case SyntaxKind.ImportSpecifier: const namedImports = token.parent.parent; if (namedImports.elements.length === 1) { // Only 1 import and it is unused. So the entire declaration should be removed. const importSpec = findImportDeclaration(token); - return createCodeFix("", importSpec.pos, importSpec.end - importSpec.pos); + return createCodeFixToRemoveNode(importSpec); } else { return removeSingleItem(namedImports.elements, token); @@ -100,17 +100,24 @@ namespace ts.codefix { const importClause = token.parent; if (!importClause.namedBindings) { // |import d from './file'| or |import * as ns from './file'| const importDecl = findImportDeclaration(importClause); - return createCodeFix("", importDecl.pos, importDecl.end - importDecl.pos); + return createCodeFixToRemoveNode(importDecl); } - else { // import |d,| * as ns from './file' - return createCodeFix("", importClause.name.pos, importClause.namedBindings.pos - importClause.name.pos); + else { + // import |d,| * as ns from './file' + const start = importClause.name.getStart(); + let end = findFirstNonSpaceCharPosStarting(importClause.name.end); + if (sourceFile.text.charCodeAt(end) === CharacterCodes.comma) { + end = findFirstNonSpaceCharPosStarting(end + 1); + } + + return createCodeFix("", start, end - start); } case SyntaxKind.NamespaceImport: const namespaceImport = token.parent; if (namespaceImport.name == token && !(namespaceImport.parent).name) { const importDecl = findImportDeclaration(namespaceImport); - return createCodeFix("", importDecl.pos, importDecl.end - importDecl.pos); + return createCodeFixToRemoveNode(importDecl); } else { const start = (namespaceImport.parent).name.end; @@ -120,16 +127,14 @@ namespace ts.codefix { break; case SyntaxKind.PropertyDeclaration: - return createCodeFix("", token.parent.pos, token.parent.end - token.parent.pos); - case SyntaxKind.NamespaceImport: - return createCodeFix("", token.parent.pos, token.parent.end - token.parent.pos); + return createCodeFixToRemoveNode(token.parent); } if (isDeclarationName(token)) { - return createCodeFix("", token.parent.pos, token.parent.end - token.parent.pos); + return createCodeFixToRemoveNode(token.parent); } else if (isLiteralComputedPropertyDeclarationName(token)) { - return createCodeFix("", token.parent.parent.pos, token.parent.parent.end - token.parent.parent.pos); + return createCodeFixToRemoveNode(token.parent.parent); } else { return undefined; @@ -144,6 +149,17 @@ namespace ts.codefix { return importDecl; } + function createCodeFixToRemoveNode(node: Node) { + return createCodeFix("", node.getStart(), node.getWidth()); + } + + function findFirstNonSpaceCharPosStarting(start: number) { + while (isWhiteSpace(sourceFile.text.charCodeAt(start))) { + start += 1; + } + return start; + } + function createCodeFix(newText: string, start: number, length: number): CodeAction[] { return [{ description: formatStringFromArgs(getLocaleSpecificMessage(Diagnostics.Remove_declaration_for_Colon_0), { 0: token.getText() }), diff --git a/tests/cases/fourslash/unusedFunctionInNamespace1.ts b/tests/cases/fourslash/unusedFunctionInNamespace1.ts index 8ebf1f7072a..288573608f2 100644 --- a/tests/cases/fourslash/unusedFunctionInNamespace1.ts +++ b/tests/cases/fourslash/unusedFunctionInNamespace1.ts @@ -2,9 +2,11 @@ // @noUnusedLocals: true //// [| namespace greeter { +//// // some legit comments //// function function1() { //// }/*1*/ //// } |] verify.rangeAfterCodeFix(`namespace greeter { + // some legit comments }`); diff --git a/tests/cases/fourslash/unusedImports3FS.ts b/tests/cases/fourslash/unusedImports3FS.ts index 98dc30c4336..6926f97bb4f 100644 --- a/tests/cases/fourslash/unusedImports3FS.ts +++ b/tests/cases/fourslash/unusedImports3FS.ts @@ -2,7 +2,7 @@ // @noUnusedLocals: true // @Filename: file2.ts -////[| import {Calculator, test, test2} from "./file1" |] +////[| import {Calculator, /*some comments*/ test, test2} from "./file1" |] //// test(); //// test2(); @@ -20,5 +20,5 @@ //// //// } -verify.rangeAfterCodeFix(`import {test, test2} from "./file1"`); +verify.rangeAfterCodeFix(`import {/*some comments*/ test, test2} from "./file1"`); From e532744f16bb79f114ea0899262a78df7610e8d8 Mon Sep 17 00:00:00 2001 From: zhengbli Date: Thu, 2 Feb 2017 14:14:40 -0800 Subject: [PATCH 35/58] Add test case for nested namespace --- .../fourslash/importNameCodeFixNewImportFile4.ts | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 tests/cases/fourslash/importNameCodeFixNewImportFile4.ts diff --git a/tests/cases/fourslash/importNameCodeFixNewImportFile4.ts b/tests/cases/fourslash/importNameCodeFixNewImportFile4.ts new file mode 100644 index 00000000000..62cf48c4977 --- /dev/null +++ b/tests/cases/fourslash/importNameCodeFixNewImportFile4.ts @@ -0,0 +1,16 @@ +/// + +//// [|let t: A/*0*/.B.I;|] + +// @Filename: ./module.ts +//// export namespace A { +//// export namespace B { +//// export interface I { } +//// } +//// } + +verify.importFixAtPosition([ +`import { A } from "./module"; + +let t: A.B.I;` +]); \ No newline at end of file From 5f1fafce5e76311cc8ef0f3c76f8b4a9008687f7 Mon Sep 17 00:00:00 2001 From: zhengbli Date: Thu, 2 Feb 2017 15:25:05 -0800 Subject: [PATCH 36/58] routine lib files update --- src/lib/dom.generated.d.ts | 1929 +++++++++++++---- src/lib/webworker.generated.d.ts | 797 +++++-- .../modularizeLibrary_Dom.iterable.types | 4 +- 3 files changed, 2202 insertions(+), 528 deletions(-) diff --git a/src/lib/dom.generated.d.ts b/src/lib/dom.generated.d.ts index d9825897ebc..b4217c131f9 100644 --- a/src/lib/dom.generated.d.ts +++ b/src/lib/dom.generated.d.ts @@ -3,18 +3,50 @@ /// IE DOM APIs ///////////////////////////// +interface Account { + rpDisplayName?: string; + displayName?: string; + id?: string; + name?: string; + imageURL?: string; +} + interface Algorithm { name: string; } -interface AriaRequestEventInit extends EventInit { - attributeName?: string; - attributeValue?: string; +interface AnimationEventInit extends EventInit { + animationName?: string; + elapsedTime?: number; } -interface CommandEventInit extends EventInit { - commandName?: string; - detail?: string; +interface AssertionOptions { + timeoutSeconds?: number; + rpId?: USVString; + allowList?: ScopedCredentialDescriptor[]; + extensions?: WebAuthnExtensions; +} + +interface CacheQueryOptions { + ignoreSearch?: boolean; + ignoreMethod?: boolean; + ignoreVary?: boolean; + cacheName?: string; +} + +interface ClientData { + challenge?: string; + origin?: string; + rpId?: string; + hashAlg?: string | Algorithm; + tokenBinding?: string; + extensions?: WebAuthnExtensions; +} + +interface CloseEventInit extends EventInit { + wasClean?: boolean; + code?: number; + reason?: string; } interface CompositionEventInit extends UIEventInit { @@ -54,6 +86,13 @@ interface CustomEventInit extends EventInit { detail?: any; } +interface DOMRectInit { + x?: any; + y?: any; + width?: any; + height?: any; +} + interface DeviceAccelerationDict { x?: number; y?: number; @@ -64,6 +103,20 @@ interface DeviceLightEventInit extends EventInit { value?: number; } +interface DeviceMotionEventInit extends EventInit { + acceleration?: DeviceAccelerationDict; + accelerationIncludingGravity?: DeviceAccelerationDict; + rotationRate?: DeviceRotationRateDict; + interval?: number; +} + +interface DeviceOrientationEventInit extends EventInit { + alpha?: number; + beta?: number; + gamma?: number; + absolute?: boolean; +} + interface DeviceRotationRateDict { alpha?: number; beta?: number; @@ -75,6 +128,14 @@ interface DoubleRange { min?: number; } +interface ErrorEventInit extends EventInit { + message?: string; + filename?: string; + lineno?: number; + colno?: number; + error?: any; +} + interface EventInit { scoped?: boolean; bubbles?: boolean; @@ -107,6 +168,29 @@ interface FocusEventInit extends UIEventInit { relatedTarget?: EventTarget; } +interface FocusNavigationEventInit extends EventInit { + navigationReason?: string; + originLeft?: number; + originTop?: number; + originWidth?: number; + originHeight?: number; +} + +interface FocusNavigationOrigin { + originLeft?: number; + originTop?: number; + originWidth?: number; + originHeight?: number; +} + +interface GamepadEventInit extends EventInit { + gamepad?: Gamepad; +} + +interface GetNotificationOptions { + tag?: string; +} + interface HashChangeEventInit extends EventInit { newURL?: string; oldURL?: string; @@ -122,6 +206,20 @@ interface IDBObjectStoreParameters { keyPath?: IDBKeyPath; } +interface IntersectionObserverEntryInit { + time?: number; + rootBounds?: DOMRectInit; + boundingClientRect?: DOMRectInit; + intersectionRect?: DOMRectInit; + target?: Element; +} + +interface IntersectionObserverInit { + root?: Element; + rootMargin?: string; + threshold?: number | number[]; +} + interface KeyAlgorithm { name?: string; } @@ -324,6 +422,11 @@ interface MSPayloadBase extends RTCStats { payloadDescription?: string; } +interface MSPortRange { + min?: number; + max?: number; +} + interface MSRelayAddress { relayAddress?: string; port?: number; @@ -374,7 +477,7 @@ interface MSUtilization { } interface MSVideoPayload extends MSPayloadBase { - resoluton?: string; + resolution?: string; videoBitRateAvg?: number; videoBitRateMax?: number; videoFrameRateAvg?: number; @@ -457,6 +560,10 @@ interface MediaStreamErrorEventInit extends EventInit { error?: MediaStreamError; } +interface MediaStreamEventInit extends EventInit { + stream?: MediaStream; +} + interface MediaStreamTrackEventInit extends EventInit { track?: MediaStreamTrack; } @@ -521,6 +628,15 @@ interface MediaTrackSupportedConstraints { groupId?: boolean; } +interface MessageEventInit extends EventInit { + lastEventId?: string; + channel?: string; + data?: any; + origin?: string; + source?: Window; + ports?: MessagePort[]; +} + interface MouseEventInit extends EventModifierInit { screenX?: number; screenY?: number; @@ -550,10 +666,68 @@ interface MutationObserverInit { attributeFilter?: string[]; } +interface NotificationOptions { + dir?: string; + lang?: string; + body?: string; + tag?: string; + icon?: string; +} + interface ObjectURLOptions { oneTimeOnly?: boolean; } +interface PaymentCurrencyAmount { + currency?: string; + value?: string; + currencySystem?: string; +} + +interface PaymentDetails { + total?: PaymentItem; + displayItems?: PaymentItem[]; + shippingOptions?: PaymentShippingOption[]; + modifiers?: PaymentDetailsModifier[]; + error?: string; +} + +interface PaymentDetailsModifier { + supportedMethods?: string[]; + total?: PaymentItem; + additionalDisplayItems?: PaymentItem[]; + data?: any; +} + +interface PaymentItem { + label?: string; + amount?: PaymentCurrencyAmount; + pending?: boolean; +} + +interface PaymentMethodData { + supportedMethods?: string[]; + data?: any; +} + +interface PaymentOptions { + requestPayerName?: boolean; + requestPayerEmail?: boolean; + requestPayerPhone?: boolean; + requestShipping?: boolean; + shippingType?: string; +} + +interface PaymentRequestUpdateEventInit extends EventInit { +} + +interface PaymentShippingOption { + id?: string; + label?: string; + amount?: PaymentCurrencyAmount; + selected?: boolean; +} + interface PeriodicWaveConstraints { disableNormalization?: boolean; } @@ -569,12 +743,34 @@ interface PointerEventInit extends MouseEventInit { isPrimary?: boolean; } +interface PopStateEventInit extends EventInit { + state?: any; +} + interface PositionOptions { enableHighAccuracy?: boolean; timeout?: number; maximumAge?: number; } +interface ProgressEventInit extends EventInit { + lengthComputable?: boolean; + loaded?: number; + total?: number; +} + +interface PushSubscriptionOptionsInit { + userVisibleOnly?: boolean; + applicationServerKey?: any; +} + +interface RTCConfiguration { + iceServers?: RTCIceServer[]; + iceTransportPolicy?: string; + bundlePolicy?: string; + peerIdentity?: string; +} + interface RTCDTMFToneChangeEventInit extends EventInit { tone?: string; } @@ -589,18 +785,6 @@ interface RTCDtlsParameters { fingerprints?: RTCDtlsFingerprint[]; } -interface RTCIceCandidate { - foundation?: string; - priority?: number; - ip?: string; - protocol?: string; - port?: number; - type?: string; - tcpType?: string; - relatedAddress?: string; - relatedPort?: number; -} - interface RTCIceCandidateAttributes extends RTCStats { ipAddress?: string; portNumber?: number; @@ -613,9 +797,28 @@ interface RTCIceCandidateAttributes extends RTCStats { interface RTCIceCandidateComplete { } +interface RTCIceCandidateDictionary { + foundation?: string; + priority?: number; + ip?: string; + protocol?: string; + port?: number; + type?: string; + tcpType?: string; + relatedAddress?: string; + relatedPort?: number; + msMTurnSessionId?: string; +} + +interface RTCIceCandidateInit { + candidate?: string; + sdpMid?: string; + sdpMLineIndex?: number; +} + interface RTCIceCandidatePair { - local?: RTCIceCandidate; - remote?: RTCIceCandidate; + local?: RTCIceCandidateDictionary; + remote?: RTCIceCandidateDictionary; } interface RTCIceCandidatePairStats extends RTCStats { @@ -637,11 +840,13 @@ interface RTCIceCandidatePairStats extends RTCStats { interface RTCIceGatherOptions { gatherPolicy?: string; iceservers?: RTCIceServer[]; + portRange?: MSPortRange; } interface RTCIceParameters { usernameFragment?: string; password?: string; + iceLite?: boolean; } interface RTCIceServer { @@ -675,6 +880,13 @@ interface RTCMediaStreamTrackStats extends RTCStats { echoReturnLossEnhancement?: number; } +interface RTCOfferOptions { + offerToReceiveVideo?: number; + offerToReceiveAudio?: number; + voiceActivityDetection?: boolean; + iceRestart?: boolean; +} + interface RTCOutboundRTPStreamStats extends RTCRTPStreamStats { packetsSent?: number; bytesSent?: number; @@ -682,6 +894,10 @@ interface RTCOutboundRTPStreamStats extends RTCRTPStreamStats { roundTripTime?: number; } +interface RTCPeerConnectionIceEventInit extends EventInit { + candidate?: RTCIceCandidate; +} + interface RTCRTPStreamStats extends RTCStats { ssrc?: string; associateStatsId?: string; @@ -719,6 +935,7 @@ interface RTCRtpCodecCapability { clockRate?: number; preferredPayloadType?: number; maxptime?: number; + ptime?: number; numChannels?: number; rtcpFeedback?: RTCRtcpFeedback[]; parameters?: any; @@ -733,6 +950,7 @@ interface RTCRtpCodecParameters { payloadType?: any; clockRate?: number; maxptime?: number; + ptime?: number; numChannels?: number; rtcpFeedback?: RTCRtcpFeedback[]; parameters?: any; @@ -752,9 +970,9 @@ interface RTCRtpEncodingParameters { priority?: number; maxBitrate?: number; minQuality?: number; - framerateBias?: number; resolutionScale?: number; framerateScale?: number; + maxFramerate?: number; active?: boolean; encodingId?: string; dependencyEncodingIds?: string[]; @@ -785,6 +1003,7 @@ interface RTCRtpParameters { headerExtensions?: RTCRtpHeaderExtensionParameters[]; encodings?: RTCRtpEncodingParameters[]; rtcp?: RTCRtcpParameters; + degradationPreference?: string; } interface RTCRtpRtxParameters { @@ -797,6 +1016,11 @@ interface RTCRtpUnhandled { muxId?: string; } +interface RTCSessionDescriptionInit { + type?: string; + sdp?: string; +} + interface RTCSrtpKeyParam { keyMethod?: string; keySalt?: string; @@ -837,6 +1061,64 @@ interface RTCTransportStats extends RTCStats { remoteCertificateId?: string; } +interface RegistrationOptions { + scope?: string; +} + +interface RequestInit { + method?: string; + headers?: any; + body?: any; + referrer?: string; + referrerPolicy?: string; + mode?: string; + credentials?: string; + cache?: string; + redirect?: string; + integrity?: string; + keepalive?: boolean; + window?: any; +} + +interface ResponseInit { + status?: number; + statusText?: string; + headers?: any; +} + +interface ScopedCredentialDescriptor { + type?: string; + id?: any; + transports?: string[]; +} + +interface ScopedCredentialOptions { + timeoutSeconds?: number; + rpId?: USVString; + excludeList?: ScopedCredentialDescriptor[]; + extensions?: WebAuthnExtensions; +} + +interface ScopedCredentialParameters { + type?: string; + algorithm?: string | Algorithm; +} + +interface ServiceWorkerMessageEventInit extends EventInit { + data?: any; + origin?: string; + lastEventId?: string; + source?: ServiceWorker | MessagePort; + ports?: MessagePort[]; +} + +interface SpeechSynthesisEventInit extends EventInit { + utterance?: SpeechSynthesisUtterance; + charIndex?: number; + elapsedTime?: number; + name?: string; +} + interface StoreExceptionsInformation extends ExceptionInformation { siteName?: string; explanationString?: string; @@ -847,11 +1129,23 @@ interface StoreSiteSpecificExceptionsInformation extends StoreExceptionsInformat arrayOfDomainStrings?: string[]; } +interface TrackEventInit extends EventInit { + track?: VideoTrack | AudioTrack | TextTrack; +} + +interface TransitionEventInit extends EventInit { + propertyName?: string; + elapsedTime?: number; +} + interface UIEventInit extends EventInit { view?: Window; detail?: number; } +interface WebAuthnExtensions { +} + interface WebGLContextAttributes { failIfMajorPerformanceCaveat?: boolean; alpha?: boolean; @@ -877,6 +1171,18 @@ interface EventListener { (evt: Event): void; } +interface WebKitEntriesCallback { + (evt: Event): void; +} + +interface WebKitErrorCallback { + (evt: Event): void; +} + +interface WebKitFileCallback { + (evt: Event): void; +} + interface ANGLE_instanced_arrays { drawArraysInstancedANGLE(mode: number, first: number, count: number, primcount: number): void; drawElementsInstancedANGLE(mode: number, count: number, type: number, offset: number, primcount: number): void; @@ -915,14 +1221,14 @@ interface AnimationEvent extends Event { declare var AnimationEvent: { prototype: AnimationEvent; - new(): AnimationEvent; + new(typeArg: string, eventInitDict?: AnimationEventInit): AnimationEvent; } interface ApplicationCacheEventMap { "cached": Event; "checking": Event; "downloading": Event; - "error": ErrorEvent; + "error": Event; "noupdate": Event; "obsolete": Event; "progress": ProgressEvent; @@ -933,7 +1239,7 @@ interface ApplicationCache extends EventTarget { oncached: (this: ApplicationCache, ev: Event) => any; onchecking: (this: ApplicationCache, ev: Event) => any; ondownloading: (this: ApplicationCache, ev: Event) => any; - onerror: (this: ApplicationCache, ev: ErrorEvent) => any; + onerror: (this: ApplicationCache, ev: Event) => any; onnoupdate: (this: ApplicationCache, ev: Event) => any; onobsolete: (this: ApplicationCache, ev: Event) => any; onprogress: (this: ApplicationCache, ev: ProgressEvent) => any; @@ -963,16 +1269,6 @@ declare var ApplicationCache: { readonly UPDATEREADY: number; } -interface AriaRequestEvent extends Event { - readonly attributeName: string; - attributeValue: string | null; -} - -declare var AriaRequestEvent: { - prototype: AriaRequestEvent; - new(type: string, eventInitDict?: AriaRequestEventInit): AriaRequestEvent; -} - interface Attr extends Node { readonly name: string; readonly ownerElement: Element; @@ -1024,12 +1320,18 @@ declare var AudioBufferSourceNode: { new(): AudioBufferSourceNode; } -interface AudioContext extends EventTarget { +interface AudioContextEventMap { + "statechange": Event; +} + +interface AudioContextBase extends EventTarget { readonly currentTime: number; readonly destination: AudioDestinationNode; readonly listener: AudioListener; + onstatechange: (this: AudioContext, ev: Event) => any; readonly sampleRate: number; - state: string; + readonly state: string; + close(): PromiseLike; createAnalyser(): AnalyserNode; createBiquadFilter(): BiquadFilterNode; createBuffer(numberOfChannels: number, length: number, sampleRate: number): AudioBuffer; @@ -1040,6 +1342,7 @@ interface AudioContext extends EventTarget { createDelay(maxDelayTime?: number): DelayNode; createDynamicsCompressor(): DynamicsCompressorNode; createGain(): GainNode; + createIIRFilter(feedforward: number[], feedback: number[]): IIRFilterNode; createMediaElementSource(mediaElement: HTMLMediaElement): MediaElementAudioSourceNode; createMediaStreamSource(mediaStream: MediaStream): MediaStreamAudioSourceNode; createOscillator(): OscillatorNode; @@ -1049,6 +1352,13 @@ interface AudioContext extends EventTarget { createStereoPanner(): StereoPannerNode; createWaveShaper(): WaveShaperNode; decodeAudioData(audioData: ArrayBuffer, successCallback?: DecodeSuccessCallback, errorCallback?: DecodeErrorCallback): PromiseLike; + resume(): PromiseLike; + addEventListener(type: K, listener: (this: AudioContext, ev: AudioContextEventMap[K]) => any, useCapture?: boolean): void; + addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void; +} + +interface AudioContext extends AudioContextBase { + suspend(): PromiseLike; } declare var AudioContext: { @@ -1085,7 +1395,7 @@ interface AudioNode extends EventTarget { readonly context: AudioContext; readonly numberOfInputs: number; readonly numberOfOutputs: number; - connect(destination: AudioNode, output?: number, input?: number): void; + connect(destination: AudioNode, output?: number, input?: number): AudioNode; disconnect(output?: number): void; disconnect(destination: AudioNode, output?: number, input?: number): void; disconnect(destination: AudioParam, output?: number): void; @@ -1099,12 +1409,12 @@ declare var AudioNode: { interface AudioParam { readonly defaultValue: number; value: number; - cancelScheduledValues(startTime: number): void; - exponentialRampToValueAtTime(value: number, endTime: number): void; - linearRampToValueAtTime(value: number, endTime: number): void; - setTargetAtTime(target: number, startTime: number, timeConstant: number): void; - setValueAtTime(value: number, startTime: number): void; - setValueCurveAtTime(values: Float32Array, startTime: number, duration: number): void; + cancelScheduledValues(startTime: number): AudioParam; + exponentialRampToValueAtTime(value: number, endTime: number): AudioParam; + linearRampToValueAtTime(value: number, endTime: number): AudioParam; + setTargetAtTime(target: number, startTime: number, timeConstant: number): AudioParam; + setValueAtTime(value: number, startTime: number): AudioParam; + setValueCurveAtTime(values: Float32Array, startTime: number, duration: number): AudioParam; } declare var AudioParam: { @@ -1481,10 +1791,16 @@ interface CSSStyleDeclaration { imeMode: string | null; justifyContent: string | null; kerning: string | null; + layoutGrid: string | null; + layoutGridChar: string | null; + layoutGridLine: string | null; + layoutGridMode: string | null; + layoutGridType: string | null; left: string | null; readonly length: number; letterSpacing: string | null; lightingColor: string | null; + lineBreak: string | null; lineHeight: string | null; listStyle: string | null; listStyleImage: string | null; @@ -1556,6 +1872,7 @@ interface CSSStyleDeclaration { orphans: string | null; outline: string | null; outlineColor: string | null; + outlineOffset: string | null; outlineStyle: string | null; outlineWidth: string | null; overflow: string | null; @@ -1576,9 +1893,11 @@ interface CSSStyleDeclaration { position: string | null; quotes: string | null; right: string | null; + rotate: string | null; rubyAlign: string | null; rubyOverhang: string | null; rubyPosition: string | null; + scale: string | null; stopColor: string | null; stopOpacity: string | null; stroke: string | null; @@ -1612,6 +1931,7 @@ interface CSSStyleDeclaration { transitionDuration: string | null; transitionProperty: string | null; transitionTimingFunction: string | null; + translate: string | null; unicodeBidi: string | null; verticalAlign: string | null; visibility: string | null; @@ -1672,6 +1992,9 @@ interface CSSStyleDeclaration { webkitTapHighlightColor: string | null; webkitTextFillColor: string | null; webkitTextSizeAdjust: any; + webkitTextStroke: string | null; + webkitTextStrokeColor: string | null; + webkitTextStrokeWidth: string | null; webkitTransform: string | null; webkitTransformOrigin: string | null; webkitTransformStyle: string | null; @@ -1693,6 +2016,7 @@ interface CSSStyleDeclaration { zIndex: string | null; zoom: string | null; resize: string | null; + userSelect: string | null; getPropertyPriority(propertyName: string): string; getPropertyValue(propertyName: string): string; item(index: number): string; @@ -1720,7 +2044,6 @@ declare var CSSStyleRule: { interface CSSStyleSheet extends StyleSheet { readonly cssRules: CSSRuleList; cssText: string; - readonly href: string; readonly id: string; readonly imports: StyleSheetList; readonly isAlternate: boolean; @@ -1752,6 +2075,34 @@ declare var CSSSupportsRule: { new(): CSSSupportsRule; } +interface Cache { + add(request: RequestInfo): PromiseLike; + addAll(requests: RequestInfo[]): PromiseLike; + delete(request: RequestInfo, options?: CacheQueryOptions): PromiseLike; + keys(request?: RequestInfo, options?: CacheQueryOptions): any; + match(request: RequestInfo, options?: CacheQueryOptions): PromiseLike; + matchAll(request?: RequestInfo, options?: CacheQueryOptions): any; + put(request: RequestInfo, response: Response): PromiseLike; +} + +declare var Cache: { + prototype: Cache; + new(): Cache; +} + +interface CacheStorage { + delete(cacheName: string): PromiseLike; + has(cacheName: string): PromiseLike; + keys(): any; + match(request: RequestInfo, options?: CacheQueryOptions): PromiseLike; + open(cacheName: string): PromiseLike; +} + +declare var CacheStorage: { + prototype: CacheStorage; + new(): CacheStorage; +} + interface CanvasGradient { addColorStop(offset: number, color: string): void; } @@ -1776,13 +2127,13 @@ interface CanvasRenderingContext2D extends Object, CanvasPathMethods { font: string; globalAlpha: number; globalCompositeOperation: string; + imageSmoothingEnabled: boolean; lineCap: string; lineDashOffset: number; lineJoin: string; lineWidth: number; miterLimit: number; msFillRule: string; - msImageSmoothingEnabled: boolean; shadowBlur: number; shadowColor: string; shadowOffsetX: number; @@ -1800,6 +2151,7 @@ interface CanvasRenderingContext2D extends Object, CanvasPathMethods { createLinearGradient(x0: number, y0: number, x1: number, y1: number): CanvasGradient; createPattern(image: HTMLImageElement | HTMLCanvasElement | HTMLVideoElement, repetition: string): CanvasPattern; createRadialGradient(x0: number, y0: number, r0: number, x1: number, y1: number, r1: number): CanvasGradient; + drawFocusIfNeeded(element: Element): void; drawImage(image: HTMLImageElement | HTMLCanvasElement | HTMLVideoElement, offsetX: number, offsetY: number, width?: number, height?: number, canvasOffsetX?: number, canvasOffsetY?: number, canvasImageWidth?: number, canvasImageHeight?: number): void; fill(fillRule?: string): void; fillRect(x: number, y: number, w: number, h: number): void; @@ -1815,7 +2167,7 @@ interface CanvasRenderingContext2D extends Object, CanvasPathMethods { scale(x: number, y: number): void; setLineDash(segments: number[]): void; setTransform(m11: number, m12: number, m21: number, m22: number, dx: number, dy: number): void; - stroke(): void; + stroke(path?: Path2D): void; strokeRect(x: number, y: number, w: number, h: number): void; strokeText(text: string, x: number, y: number, maxWidth?: number): void; transform(m11: number, m12: number, m21: number, m22: number, dx: number, dy: number): void; @@ -1901,17 +2253,7 @@ interface CloseEvent extends Event { declare var CloseEvent: { prototype: CloseEvent; - new(): CloseEvent; -} - -interface CommandEvent extends Event { - readonly commandName: string; - readonly detail: string | null; -} - -declare var CommandEvent: { - prototype: CommandEvent; - new(type: string, eventInitDict?: CommandEventInit): CommandEvent; + new(typeArg: string, eventInitDict?: CloseEventInit): CloseEvent; } interface Comment extends CharacterData { @@ -1938,7 +2280,7 @@ interface Console { assert(test?: boolean, message?: string, ...optionalParams: any[]): void; clear(): void; count(countTitle?: string): void; - debug(message?: string, ...optionalParams: any[]): void; + debug(message?: any, ...optionalParams: any[]): void; dir(value?: any, ...optionalParams: any[]): void; dirxml(value: any): void; error(message?: any, ...optionalParams: any[]): void; @@ -2108,9 +2450,9 @@ declare var DOMException: { interface DOMImplementation { createDocument(namespaceURI: string | null, qualifiedName: string | null, doctype: DocumentType): Document; - createDocumentType(qualifiedName: string, publicId: string | null, systemId: string | null): DocumentType; + createDocumentType(qualifiedName: string, publicId: string, systemId: string): DocumentType; createHTMLDocument(title: string): Document; - hasFeature(feature: string | null, version: string | null): boolean; + hasFeature(): boolean; } declare var DOMImplementation: { @@ -2149,7 +2491,7 @@ declare var DOMStringList: { } interface DOMStringMap { - [name: string]: string; + [name: string]: string | undefined; } declare var DOMStringMap: { @@ -2175,7 +2517,7 @@ declare var DOMTokenList: { interface DataCue extends TextTrackCue { data: ArrayBuffer; - addEventListener(type: K, listener: (this: TextTrackCue, ev: TextTrackCueEventMap[K]) => any, useCapture?: boolean): void; + addEventListener(type: K, listener: (this: DataCue, ev: TextTrackCueEventMap[K]) => any, useCapture?: boolean): void; addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void; } @@ -2205,6 +2547,7 @@ interface DataTransferItem { readonly type: string; getAsFile(): File | null; getAsString(_callback: FunctionStringCallback | null): void; + webkitGetAsEntry(): any; } declare var DataTransferItem: { @@ -2265,7 +2608,7 @@ interface DeviceLightEvent extends Event { declare var DeviceLightEvent: { prototype: DeviceLightEvent; - new(type: string, eventInitDict?: DeviceLightEventInit): DeviceLightEvent; + new(typeArg: string, eventInitDict?: DeviceLightEventInit): DeviceLightEvent; } interface DeviceMotionEvent extends Event { @@ -2278,7 +2621,7 @@ interface DeviceMotionEvent extends Event { declare var DeviceMotionEvent: { prototype: DeviceMotionEvent; - new(): DeviceMotionEvent; + new(typeArg: string, eventInitDict?: DeviceMotionEventInit): DeviceMotionEvent; } interface DeviceOrientationEvent extends Event { @@ -2291,7 +2634,7 @@ interface DeviceOrientationEvent extends Event { declare var DeviceOrientationEvent: { prototype: DeviceOrientationEvent; - new(): DeviceOrientationEvent; + new(typeArg: string, eventInitDict?: DeviceOrientationEventInit): DeviceOrientationEvent; } interface DeviceRotationRate { @@ -2373,7 +2716,7 @@ interface DocumentEventMap extends GlobalEventHandlersEventMap { "pointerlockerror": Event; "progress": ProgressEvent; "ratechange": Event; - "readystatechange": ProgressEvent; + "readystatechange": Event; "reset": Event; "scroll": UIEvent; "seeked": Event; @@ -2444,10 +2787,6 @@ interface Document extends Node, GlobalEventHandlers, NodeSelector, DocumentEven readonly compatMode: string; cookie: string; readonly currentScript: HTMLScriptElement | SVGScriptElement; - /** - * Gets the default character set from the current regional language settings. - */ - readonly defaultCharset: string; readonly defaultView: Window; /** * Sets or gets a value that indicates whether the document can be edited. @@ -2754,7 +3093,7 @@ interface Document extends Node, GlobalEventHandlers, NodeSelector, DocumentEven * Fires when the state of the object has changed. * @param ev The event */ - onreadystatechange: (this: Document, ev: ProgressEvent) => any; + onreadystatechange: (this: Document, ev: Event) => any; /** * Fires when the user resets a form. * @param ev The event. @@ -3122,8 +3461,8 @@ interface DocumentType extends Node, ChildNode { readonly internalSubset: string | null; readonly name: string; readonly notations: NamedNodeMap; - readonly publicId: string | null; - readonly systemId: string | null; + readonly publicId: string; + readonly systemId: string; } declare var DocumentType: { @@ -3146,7 +3485,7 @@ interface DynamicsCompressorNode extends AudioNode { readonly attack: AudioParam; readonly knee: AudioParam; readonly ratio: AudioParam; - readonly reduction: AudioParam; + readonly reduction: number; readonly release: AudioParam; readonly threshold: AudioParam; } @@ -3177,8 +3516,8 @@ declare var EXT_texture_filter_anisotropic: { } interface ElementEventMap extends GlobalEventHandlersEventMap { - "ariarequest": AriaRequestEvent; - "command": CommandEvent; + "ariarequest": Event; + "command": Event; "gotpointercapture": PointerEvent; "lostpointercapture": PointerEvent; "MSGestureChange": MSGestureEvent; @@ -3214,10 +3553,11 @@ interface Element extends Node, GlobalEventHandlers, ElementTraversal, NodeSelec readonly clientTop: number; readonly clientWidth: number; id: string; + innerHTML: string; msContentZoomFactor: number; readonly msRegionOverflow: string; - onariarequest: (this: Element, ev: AriaRequestEvent) => any; - oncommand: (this: Element, ev: CommandEvent) => any; + onariarequest: (this: Element, ev: Event) => any; + oncommand: (this: Element, ev: Event) => any; ongotpointercapture: (this: Element, ev: PointerEvent) => any; onlostpointercapture: (this: Element, ev: PointerEvent) => any; onmsgesturechange: (this: Element, ev: MSGestureEvent) => any; @@ -3243,13 +3583,13 @@ interface Element extends Node, GlobalEventHandlers, ElementTraversal, NodeSelec ontouchstart: (ev: TouchEvent) => any; onwebkitfullscreenchange: (this: Element, ev: Event) => any; onwebkitfullscreenerror: (this: Element, ev: Event) => any; + outerHTML: string; readonly prefix: string | null; readonly scrollHeight: number; scrollLeft: number; scrollTop: number; readonly scrollWidth: number; readonly tagName: string; - innerHTML: string; readonly assignedSlot: HTMLSlotElement | null; slot: string; readonly shadowRoot: ShadowRoot | null; @@ -3273,7 +3613,7 @@ interface Element extends Node, GlobalEventHandlers, ElementTraversal, NodeSelec msSetPointerCapture(pointerId: number): void; msZoomTo(args: MsZoomToOptions): void; releasePointerCapture(pointerId: number): void; - removeAttribute(name?: string): void; + removeAttribute(qualifiedName: string): void; removeAttributeNS(namespaceURI: string, localName: string): void; removeAttributeNode(oldAttr: Attr): Attr; requestFullscreen(): void; @@ -3320,7 +3660,7 @@ interface ErrorEvent extends Event { declare var ErrorEvent: { prototype: ErrorEvent; - new(): ErrorEvent; + new(type: string, errorEventInitDict?: ErrorEventInit): ErrorEvent; } interface Event { @@ -3349,7 +3689,7 @@ interface Event { declare var Event: { prototype: Event; - new(type: string, eventInitDict?: EventInit): Event; + new(typeArg: string, eventInitDict?: EventInit): Event; readonly AT_TARGET: number; readonly BUBBLING_PHASE: number; readonly CAPTURING_PHASE: number; @@ -3366,6 +3706,21 @@ declare var EventTarget: { new(): EventTarget; } +interface ExtensionScriptApis { + extensionIdToShortId(extensionId: string): number; + fireExtensionApiTelemetry(functionName: string, isSucceeded: boolean, isSupported: boolean): void; + genericFunction(routerAddress: any, parameters?: string, callbackId?: number): void; + genericSynchronousFunction(functionId: number, parameters?: string): string; + getExtensionId(): string; + registerGenericFunctionCallbackHandler(callbackHandler: any): void; + registerGenericPersistentCallbackHandler(callbackHandler: any): void; +} + +declare var ExtensionScriptApis: { + prototype: ExtensionScriptApis; + new(): ExtensionScriptApis; +} + interface External { } @@ -3402,7 +3757,7 @@ interface FileReader extends EventTarget, MSBaseReader { readAsBinaryString(blob: Blob): void; readAsDataURL(blob: Blob): void; readAsText(blob: Blob, encoding?: string): void; - addEventListener(type: K, listener: (this: MSBaseReader, ev: MSBaseReaderEventMap[K]) => any, useCapture?: boolean): void; + addEventListener(type: K, listener: (this: FileReader, ev: MSBaseReaderEventMap[K]) => any, useCapture?: boolean): void; addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void; } @@ -3421,6 +3776,20 @@ declare var FocusEvent: { new(typeArg: string, eventInitDict?: FocusEventInit): FocusEvent; } +interface FocusNavigationEvent extends Event { + readonly navigationReason: string; + readonly originHeight: number; + readonly originLeft: number; + readonly originTop: number; + readonly originWidth: number; + requestFocus(): void; +} + +declare var FocusNavigationEvent: { + prototype: FocusNavigationEvent; + new(type: string, eventInitDict?: FocusNavigationEventInit): FocusNavigationEvent; +} + interface FormData { append(name: any, value: any, blobName?: string): void; } @@ -3470,7 +3839,7 @@ interface GamepadEvent extends Event { declare var GamepadEvent: { prototype: GamepadEvent; - new(): GamepadEvent; + new(typeArg: string, eventInitDict?: GamepadEventInit): GamepadEvent; } interface Geolocation { @@ -3484,8 +3853,11 @@ declare var Geolocation: { new(): Geolocation; } -interface HTMLAllCollection extends HTMLCollection { - namedItem(name: string): Element; +interface HTMLAllCollection { + readonly length: number; + item(nameOrIndex?: string): HTMLCollection | Element | null; + namedItem(name: string): HTMLCollection | Element | null; + [index: number]: Element; } declare var HTMLAllCollection: { @@ -3573,7 +3945,7 @@ interface HTMLAnchorElement extends HTMLElement { * Returns a string representation of an object. */ toString(): string; - addEventListener(type: K, listener: (this: HTMLElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void; + addEventListener(type: K, listener: (this: HTMLAnchorElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void; addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void; } @@ -3647,7 +4019,7 @@ interface HTMLAppletElement extends HTMLElement { useMap: string; vspace: number; width: number; - addEventListener(type: K, listener: (this: HTMLElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void; + addEventListener(type: K, listener: (this: HTMLAppletElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void; addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void; } @@ -3715,7 +4087,7 @@ interface HTMLAreaElement extends HTMLElement { * Returns a string representation of an object. */ toString(): string; - addEventListener(type: K, listener: (this: HTMLElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void; + addEventListener(type: K, listener: (this: HTMLAreaElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void; addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void; } @@ -3724,15 +4096,7 @@ declare var HTMLAreaElement: { new(): HTMLAreaElement; } -interface HTMLAreasCollection extends HTMLCollection { - /** - * Adds an element to the areas, controlRange, or options collection. - */ - add(element: HTMLElement, before?: HTMLElement | number): void; - /** - * Removes an element from the collection. - */ - remove(index?: number): void; +interface HTMLAreasCollection extends HTMLCollectionBase { } declare var HTMLAreasCollection: { @@ -3741,7 +4105,7 @@ declare var HTMLAreasCollection: { } interface HTMLAudioElement extends HTMLMediaElement { - addEventListener(type: K, listener: (this: HTMLMediaElement, ev: HTMLMediaElementEventMap[K]) => any, useCapture?: boolean): void; + addEventListener(type: K, listener: (this: HTMLAudioElement, ev: HTMLMediaElementEventMap[K]) => any, useCapture?: boolean): void; addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void; } @@ -3755,7 +4119,7 @@ interface HTMLBRElement extends HTMLElement { * Sets or retrieves the side on which floating objects are not to be positioned when any IHTMLBlockElement is inserted into the document. */ clear: string; - addEventListener(type: K, listener: (this: HTMLElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void; + addEventListener(type: K, listener: (this: HTMLBRElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void; addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void; } @@ -3773,7 +4137,7 @@ interface HTMLBaseElement extends HTMLElement { * Sets or retrieves the window or frame at which to target content. */ target: string; - addEventListener(type: K, listener: (this: HTMLElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void; + addEventListener(type: K, listener: (this: HTMLBaseElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void; addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void; } @@ -3791,7 +4155,7 @@ interface HTMLBaseFontElement extends HTMLElement, DOML2DeprecatedColorProperty * Sets or retrieves the font size of the object. */ size: number; - addEventListener(type: K, listener: (this: HTMLElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void; + addEventListener(type: K, listener: (this: HTMLBaseFontElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void; addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void; } @@ -3817,6 +4181,7 @@ interface HTMLBodyElementEventMap extends HTMLElementEventMap { "pageshow": PageTransitionEvent; "popstate": PopStateEvent; "resize": UIEvent; + "scroll": UIEvent; "storage": StorageEvent; "unload": Event; } @@ -3844,6 +4209,7 @@ interface HTMLBodyElement extends HTMLElement { onpageshow: (this: HTMLBodyElement, ev: PageTransitionEvent) => any; onpopstate: (this: HTMLBodyElement, ev: PopStateEvent) => any; onresize: (this: HTMLBodyElement, ev: UIEvent) => any; + onscroll: (this: HTMLBodyElement, ev: UIEvent) => any; onstorage: (this: HTMLBodyElement, ev: StorageEvent) => any; onunload: (this: HTMLBodyElement, ev: Event) => any; text: any; @@ -3921,7 +4287,7 @@ interface HTMLButtonElement extends HTMLElement { * @param error Sets a custom error message that is displayed when a form is submitted. */ setCustomValidity(error: string): void; - addEventListener(type: K, listener: (this: HTMLElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void; + addEventListener(type: K, listener: (this: HTMLButtonElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void; addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void; } @@ -3956,7 +4322,7 @@ interface HTMLCanvasElement extends HTMLElement { */ toDataURL(type?: string, ...args: any[]): string; toBlob(callback: (result: Blob | null) => void, type?: string, ...arguments: any[]): void; - addEventListener(type: K, listener: (this: HTMLElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void; + addEventListener(type: K, listener: (this: HTMLCanvasElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void; addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void; } @@ -3965,7 +4331,7 @@ declare var HTMLCanvasElement: { new(): HTMLCanvasElement; } -interface HTMLCollection { +interface HTMLCollectionBase { /** * Sets or retrieves the number of objects in a collection. */ @@ -3974,11 +4340,14 @@ interface HTMLCollection { * Retrieves an object from various collections. */ item(index: number): Element; + [index: number]: Element; +} + +interface HTMLCollection extends HTMLCollectionBase { /** * Retrieves a select object or an object from an options collection. */ - namedItem(name: string): Element; - [index: number]: Element; + namedItem(name: string): Element | null; } declare var HTMLCollection: { @@ -3988,7 +4357,7 @@ declare var HTMLCollection: { interface HTMLDListElement extends HTMLElement { compact: boolean; - addEventListener(type: K, listener: (this: HTMLElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void; + addEventListener(type: K, listener: (this: HTMLDListElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void; addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void; } @@ -3997,9 +4366,20 @@ declare var HTMLDListElement: { new(): HTMLDListElement; } +interface HTMLDataElement extends HTMLElement { + value: string; + addEventListener(type: K, listener: (this: HTMLDataElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void; + addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void; +} + +declare var HTMLDataElement: { + prototype: HTMLDataElement; + new(): HTMLDataElement; +} + interface HTMLDataListElement extends HTMLElement { options: HTMLCollectionOf; - addEventListener(type: K, listener: (this: HTMLElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void; + addEventListener(type: K, listener: (this: HTMLDataListElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void; addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void; } @@ -4010,7 +4390,7 @@ declare var HTMLDataListElement: { interface HTMLDirectoryElement extends HTMLElement { compact: boolean; - addEventListener(type: K, listener: (this: HTMLElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void; + addEventListener(type: K, listener: (this: HTMLDirectoryElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void; addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void; } @@ -4028,7 +4408,7 @@ interface HTMLDivElement extends HTMLElement { * Sets or retrieves whether the browser automatically performs wordwrap. */ noWrap: boolean; - addEventListener(type: K, listener: (this: HTMLElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void; + addEventListener(type: K, listener: (this: HTMLDivElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void; addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void; } @@ -4038,7 +4418,7 @@ declare var HTMLDivElement: { } interface HTMLDocument extends Document { - addEventListener(type: K, listener: (this: Document, ev: DocumentEventMap[K]) => any, useCapture?: boolean): void; + addEventListener(type: K, listener: (this: HTMLDocument, ev: DocumentEventMap[K]) => any, useCapture?: boolean): void; addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void; } @@ -4126,7 +4506,6 @@ interface HTMLElement extends Element { draggable: boolean; hidden: boolean; hideFocus: boolean; - innerHTML: string; innerText: string; readonly isContentEditable: boolean; lang: string; @@ -4202,7 +4581,6 @@ interface HTMLElement extends Element { ontimeupdate: (this: HTMLElement, ev: Event) => any; onvolumechange: (this: HTMLElement, ev: Event) => any; onwaiting: (this: HTMLElement, ev: Event) => any; - outerHTML: string; outerText: string; spellcheck: boolean; readonly style: CSSStyleDeclaration; @@ -4213,7 +4591,6 @@ interface HTMLElement extends Element { dragDrop(): boolean; focus(): void; msGetInputContext(): MSInputMethodContext; - setActive(): void; addEventListener(type: K, listener: (this: HTMLElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void; addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void; } @@ -4270,7 +4647,7 @@ interface HTMLEmbedElement extends HTMLElement, GetSVGDocument { * Sets or retrieves the width of the object. */ width: string; - addEventListener(type: K, listener: (this: HTMLElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void; + addEventListener(type: K, listener: (this: HTMLEmbedElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void; addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void; } @@ -4289,6 +4666,7 @@ interface HTMLFieldSetElement extends HTMLElement { * Retrieves a reference to the form that the object is embedded in. */ readonly form: HTMLFormElement; + name: string; /** * Returns the error message that would be displayed if the user submits the form, or an empty string if no error message. It also triggers the standard error message, such as "this is a required field". The result is that the user sees validation messages without actually submitting. */ @@ -4310,7 +4688,7 @@ interface HTMLFieldSetElement extends HTMLElement { * @param error Sets a custom error message that is displayed when a form is submitted. */ setCustomValidity(error: string): void; - addEventListener(type: K, listener: (this: HTMLElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void; + addEventListener(type: K, listener: (this: HTMLFieldSetElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void; addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void; } @@ -4324,7 +4702,7 @@ interface HTMLFontElement extends HTMLElement, DOML2DeprecatedColorProperty, DOM * Sets or retrieves the current typeface family. */ face: string; - addEventListener(type: K, listener: (this: HTMLElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void; + addEventListener(type: K, listener: (this: HTMLFontElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void; addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void; } @@ -4333,6 +4711,15 @@ declare var HTMLFontElement: { new(): HTMLFontElement; } +interface HTMLFormControlsCollection extends HTMLCollectionBase { + namedItem(name: string): HTMLCollection | Element | null; +} + +declare var HTMLFormControlsCollection: { + prototype: HTMLFormControlsCollection; + new(): HTMLFormControlsCollection; +} + interface HTMLFormElement extends HTMLElement { /** * Sets or retrieves a list of character encodings for input data that must be accepted by the server processing the form. @@ -4349,7 +4736,7 @@ interface HTMLFormElement extends HTMLElement { /** * Retrieves a collection, in source order, of all controls in a given form. */ - readonly elements: HTMLCollection; + readonly elements: HTMLFormControlsCollection; /** * Sets or retrieves the MIME encoding for the form. */ @@ -4400,7 +4787,7 @@ interface HTMLFormElement extends HTMLElement { * Fires when a FORM is about to be submitted. */ submit(): void; - addEventListener(type: K, listener: (this: HTMLElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void; + addEventListener(type: K, listener: (this: HTMLFormElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void; addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void; [name: string]: any; } @@ -4489,6 +4876,7 @@ declare var HTMLFrameElement: { } interface HTMLFrameSetElementEventMap extends HTMLElementEventMap { + "afterprint": Event; "beforeprint": Event; "beforeunload": BeforeUnloadEvent; "blur": FocusEvent; @@ -4502,7 +4890,9 @@ interface HTMLFrameSetElementEventMap extends HTMLElementEventMap { "orientationchange": Event; "pagehide": PageTransitionEvent; "pageshow": PageTransitionEvent; + "popstate": PopStateEvent; "resize": UIEvent; + "scroll": UIEvent; "storage": StorageEvent; "unload": Event; } @@ -4546,7 +4936,9 @@ interface HTMLFrameSetElement extends HTMLElement { onorientationchange: (this: HTMLFrameSetElement, ev: Event) => any; onpagehide: (this: HTMLFrameSetElement, ev: PageTransitionEvent) => any; onpageshow: (this: HTMLFrameSetElement, ev: PageTransitionEvent) => any; + onpopstate: (this: HTMLFrameSetElement, ev: PopStateEvent) => any; onresize: (this: HTMLFrameSetElement, ev: UIEvent) => any; + onscroll: (this: HTMLFrameSetElement, ev: UIEvent) => any; onstorage: (this: HTMLFrameSetElement, ev: StorageEvent) => any; onunload: (this: HTMLFrameSetElement, ev: Event) => any; /** @@ -4575,7 +4967,7 @@ interface HTMLHRElement extends HTMLElement, DOML2DeprecatedColorProperty, DOML2 * Sets or retrieves the width of the object. */ width: number; - addEventListener(type: K, listener: (this: HTMLElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void; + addEventListener(type: K, listener: (this: HTMLHRElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void; addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void; } @@ -4586,7 +4978,7 @@ declare var HTMLHRElement: { interface HTMLHeadElement extends HTMLElement { profile: string; - addEventListener(type: K, listener: (this: HTMLElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void; + addEventListener(type: K, listener: (this: HTMLHeadElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void; addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void; } @@ -4600,7 +4992,7 @@ interface HTMLHeadingElement extends HTMLElement { * Sets or retrieves a value that indicates the table alignment. */ align: string; - addEventListener(type: K, listener: (this: HTMLElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void; + addEventListener(type: K, listener: (this: HTMLHeadingElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void; addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void; } @@ -4614,7 +5006,7 @@ interface HTMLHtmlElement extends HTMLElement { * Sets or retrieves the DTD version that governs the current document. */ version: string; - addEventListener(type: K, listener: (this: HTMLElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void; + addEventListener(type: K, listener: (this: HTMLHtmlElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void; addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void; } @@ -4633,6 +5025,7 @@ interface HTMLIFrameElement extends HTMLElement, GetSVGDocument { */ align: string; allowFullscreen: boolean; + allowPaymentRequest: boolean; /** * Specifies the properties of a border drawn around an object. */ @@ -4728,7 +5121,7 @@ interface HTMLImageElement extends HTMLElement { * Retrieves whether the object is fully loaded. */ readonly complete: boolean; - crossOrigin: string; + crossOrigin: string | null; readonly currentSrc: string; /** * Sets or retrieves the height of the object. @@ -4793,14 +5186,13 @@ interface HTMLImageElement extends HTMLElement { readonly x: number; readonly y: number; msGetAsCastingSource(): any; - addEventListener(type: K, listener: (this: HTMLElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void; + addEventListener(type: K, listener: (this: HTMLImageElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void; addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void; } declare var HTMLImageElement: { prototype: HTMLImageElement; new(): HTMLImageElement; - create(): HTMLImageElement; } interface HTMLInputElement extends HTMLElement { @@ -5006,7 +5398,7 @@ interface HTMLInputElement extends HTMLElement { * @param n Value to increment the value by. */ stepUp(n?: number): void; - addEventListener(type: K, listener: (this: HTMLElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void; + addEventListener(type: K, listener: (this: HTMLInputElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void; addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void; } @@ -5021,7 +5413,7 @@ interface HTMLLIElement extends HTMLElement { * Sets or retrieves the value of a list item. */ value: number; - addEventListener(type: K, listener: (this: HTMLElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void; + addEventListener(type: K, listener: (this: HTMLLIElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void; addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void; } @@ -5039,7 +5431,7 @@ interface HTMLLabelElement extends HTMLElement { * Sets or retrieves the object to which the given label object is assigned. */ htmlFor: string; - addEventListener(type: K, listener: (this: HTMLElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void; + addEventListener(type: K, listener: (this: HTMLLabelElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void; addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void; } @@ -5057,7 +5449,7 @@ interface HTMLLegendElement extends HTMLElement { * Retrieves a reference to the form that the object is embedded in. */ readonly form: HTMLFormElement; - addEventListener(type: K, listener: (this: HTMLElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void; + addEventListener(type: K, listener: (this: HTMLLegendElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void; addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void; } @@ -5102,7 +5494,7 @@ interface HTMLLinkElement extends HTMLElement, LinkStyle { type: string; import?: Document; integrity: string; - addEventListener(type: K, listener: (this: HTMLElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void; + addEventListener(type: K, listener: (this: HTMLLinkElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void; addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void; } @@ -5120,7 +5512,7 @@ interface HTMLMapElement extends HTMLElement { * Sets or retrieves the name of the object. */ name: string; - addEventListener(type: K, listener: (this: HTMLElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void; + addEventListener(type: K, listener: (this: HTMLMapElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void; addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void; } @@ -5183,7 +5575,7 @@ interface HTMLMediaElement extends HTMLElement { * Gets or sets a flag that indicates whether the client provides a set of controls for the media (in case the developer does not include controls for the player). */ controls: boolean; - crossOrigin: string; + crossOrigin: string | null; /** * Gets the address or URL of the current media resource that is selected by IHTMLMediaElement. */ @@ -5355,7 +5747,7 @@ declare var HTMLMediaElement: { interface HTMLMenuElement extends HTMLElement { compact: boolean; type: string; - addEventListener(type: K, listener: (this: HTMLElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void; + addEventListener(type: K, listener: (this: HTMLMenuElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void; addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void; } @@ -5389,7 +5781,7 @@ interface HTMLMetaElement extends HTMLElement { * Sets or retrieves the URL property that will be loaded after the specified time has elapsed. */ url: string; - addEventListener(type: K, listener: (this: HTMLElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void; + addEventListener(type: K, listener: (this: HTMLMetaElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void; addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void; } @@ -5405,7 +5797,7 @@ interface HTMLMeterElement extends HTMLElement { min: number; optimum: number; value: number; - addEventListener(type: K, listener: (this: HTMLElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void; + addEventListener(type: K, listener: (this: HTMLMeterElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void; addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void; } @@ -5423,7 +5815,7 @@ interface HTMLModElement extends HTMLElement { * Sets or retrieves the date and time of a modification to the object. */ dateTime: string; - addEventListener(type: K, listener: (this: HTMLElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void; + addEventListener(type: K, listener: (this: HTMLModElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void; addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void; } @@ -5439,7 +5831,7 @@ interface HTMLOListElement extends HTMLElement { */ start: number; type: string; - addEventListener(type: K, listener: (this: HTMLElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void; + addEventListener(type: K, listener: (this: HTMLOListElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void; addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void; } @@ -5517,10 +5909,6 @@ interface HTMLObjectElement extends HTMLElement, GetSVGDocument { * Sets or retrieves the name of the object. */ name: string; - /** - * Retrieves the contained object. - */ - readonly object: any; readonly readyState: number; /** * Sets or retrieves a message to be displayed while an object is loading. @@ -5560,7 +5948,7 @@ interface HTMLObjectElement extends HTMLElement, GetSVGDocument { * @param error Sets a custom error message that is displayed when a form is submitted. */ setCustomValidity(error: string): void; - addEventListener(type: K, listener: (this: HTMLElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void; + addEventListener(type: K, listener: (this: HTMLObjectElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void; addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void; } @@ -5599,7 +5987,7 @@ interface HTMLOptGroupElement extends HTMLElement { * Sets or retrieves the value which is returned to the server when the form control is submitted. */ value: string; - addEventListener(type: K, listener: (this: HTMLElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void; + addEventListener(type: K, listener: (this: HTMLOptGroupElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void; addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void; } @@ -5638,14 +6026,13 @@ interface HTMLOptionElement extends HTMLElement { * Sets or retrieves the value which is returned to the server when the form control is submitted. */ value: string; - addEventListener(type: K, listener: (this: HTMLElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void; + addEventListener(type: K, listener: (this: HTMLOptionElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void; addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void; } declare var HTMLOptionElement: { prototype: HTMLOptionElement; new(): HTMLOptionElement; - create(): HTMLOptionElement; } interface HTMLOptionsCollection extends HTMLCollectionOf { @@ -5660,13 +6047,35 @@ declare var HTMLOptionsCollection: { new(): HTMLOptionsCollection; } +interface HTMLOutputElement extends HTMLElement { + defaultValue: string; + readonly form: HTMLFormElement; + readonly htmlFor: DOMSettableTokenList; + name: string; + readonly type: string; + readonly validationMessage: string; + readonly validity: ValidityState; + value: string; + readonly willValidate: boolean; + checkValidity(): boolean; + reportValidity(): boolean; + setCustomValidity(error: string): void; + addEventListener(type: K, listener: (this: HTMLOutputElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void; + addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void; +} + +declare var HTMLOutputElement: { + prototype: HTMLOutputElement; + new(): HTMLOutputElement; +} + interface HTMLParagraphElement extends HTMLElement { /** * Sets or retrieves how the object is aligned with adjacent text. */ align: string; clear: string; - addEventListener(type: K, listener: (this: HTMLElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void; + addEventListener(type: K, listener: (this: HTMLParagraphElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void; addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void; } @@ -5692,7 +6101,7 @@ interface HTMLParamElement extends HTMLElement { * Sets or retrieves the data type of the value attribute. */ valueType: string; - addEventListener(type: K, listener: (this: HTMLElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void; + addEventListener(type: K, listener: (this: HTMLParamElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void; addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void; } @@ -5702,7 +6111,7 @@ declare var HTMLParamElement: { } interface HTMLPictureElement extends HTMLElement { - addEventListener(type: K, listener: (this: HTMLElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void; + addEventListener(type: K, listener: (this: HTMLPictureElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void; addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void; } @@ -5716,7 +6125,7 @@ interface HTMLPreElement extends HTMLElement { * Sets or gets a value that you can use to implement your own width functionality for the object. */ width: number; - addEventListener(type: K, listener: (this: HTMLElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void; + addEventListener(type: K, listener: (this: HTMLPreElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void; addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void; } @@ -5742,7 +6151,7 @@ interface HTMLProgressElement extends HTMLElement { * Sets or gets the current value of a progress element. The value must be a non-negative number between 0 and the max value. */ value: number; - addEventListener(type: K, listener: (this: HTMLElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void; + addEventListener(type: K, listener: (this: HTMLProgressElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void; addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void; } @@ -5756,7 +6165,7 @@ interface HTMLQuoteElement extends HTMLElement { * Sets or retrieves reference information about the object. */ cite: string; - addEventListener(type: K, listener: (this: HTMLElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void; + addEventListener(type: K, listener: (this: HTMLQuoteElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void; addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void; } @@ -5771,6 +6180,7 @@ interface HTMLScriptElement extends HTMLElement { * Sets or retrieves the character set used to encode the object. */ charset: string; + crossOrigin: string | null; /** * Sets or retrieves the status of the script. */ @@ -5796,7 +6206,7 @@ interface HTMLScriptElement extends HTMLElement { */ type: string; integrity: string; - addEventListener(type: K, listener: (this: HTMLElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void; + addEventListener(type: K, listener: (this: HTMLScriptElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void; addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void; } @@ -5892,7 +6302,7 @@ interface HTMLSelectElement extends HTMLElement { * @param error Sets a custom error message that is displayed when a form is submitted. */ setCustomValidity(error: string): void; - addEventListener(type: K, listener: (this: HTMLElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void; + addEventListener(type: K, listener: (this: HTMLSelectElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void; addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void; [name: string]: any; } @@ -5918,7 +6328,7 @@ interface HTMLSourceElement extends HTMLElement { * Gets or sets the MIME type of a media resource. */ type: string; - addEventListener(type: K, listener: (this: HTMLElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void; + addEventListener(type: K, listener: (this: HTMLSourceElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void; addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void; } @@ -5928,7 +6338,7 @@ declare var HTMLSourceElement: { } interface HTMLSpanElement extends HTMLElement { - addEventListener(type: K, listener: (this: HTMLElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void; + addEventListener(type: K, listener: (this: HTMLSpanElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void; addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void; } @@ -5947,7 +6357,7 @@ interface HTMLStyleElement extends HTMLElement, LinkStyle { * Retrieves the CSS language in which the style sheet is written. */ type: string; - addEventListener(type: K, listener: (this: HTMLElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void; + addEventListener(type: K, listener: (this: HTMLStyleElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void; addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void; } @@ -5965,7 +6375,7 @@ interface HTMLTableCaptionElement extends HTMLElement { * Sets or retrieves whether the caption appears at the top or bottom of the table. */ vAlign: string; - addEventListener(type: K, listener: (this: HTMLElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void; + addEventListener(type: K, listener: (this: HTMLTableCaptionElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void; addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void; } @@ -6020,7 +6430,7 @@ interface HTMLTableCellElement extends HTMLElement, HTMLTableAlignment { * Sets or retrieves the width of the object. */ width: string; - addEventListener(type: K, listener: (this: HTMLElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void; + addEventListener(type: K, listener: (this: HTMLTableCellElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void; addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void; } @@ -6042,7 +6452,7 @@ interface HTMLTableColElement extends HTMLElement, HTMLTableAlignment { * Sets or retrieves the width of the object. */ width: any; - addEventListener(type: K, listener: (this: HTMLElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void; + addEventListener(type: K, listener: (this: HTMLTableColElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void; addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void; } @@ -6052,6 +6462,8 @@ declare var HTMLTableColElement: { } interface HTMLTableDataCellElement extends HTMLTableCellElement { + addEventListener(type: K, listener: (this: HTMLTableDataCellElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void; + addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void; } declare var HTMLTableDataCellElement: { @@ -6163,7 +6575,7 @@ interface HTMLTableElement extends HTMLElement { * @param index Number that specifies where to insert the row in the rows collection. The default value is -1, which appends the new row to the end of the rows collection. */ insertRow(index?: number): HTMLTableRowElement; - addEventListener(type: K, listener: (this: HTMLElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void; + addEventListener(type: K, listener: (this: HTMLTableElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void; addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void; } @@ -6177,6 +6589,8 @@ interface HTMLTableHeaderCellElement extends HTMLTableCellElement { * Sets or retrieves the group of cells in a table to which the object's information applies. */ scope: string; + addEventListener(type: K, listener: (this: HTMLTableHeaderCellElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void; + addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void; } declare var HTMLTableHeaderCellElement: { @@ -6216,7 +6630,7 @@ interface HTMLTableRowElement extends HTMLElement, HTMLTableAlignment { * @param index Number that specifies where to insert the cell in the tr. The default value is -1, which appends the new cell to the end of the cells collection. */ insertCell(index?: number): HTMLTableDataCellElement; - addEventListener(type: K, listener: (this: HTMLElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void; + addEventListener(type: K, listener: (this: HTMLTableRowElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void; addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void; } @@ -6244,7 +6658,7 @@ interface HTMLTableSectionElement extends HTMLElement, HTMLTableAlignment { * @param index Number that specifies where to insert the row in the rows collection. The default value is -1, which appends the new row to the end of the rows collection. */ insertRow(index?: number): HTMLTableRowElement; - addEventListener(type: K, listener: (this: HTMLElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void; + addEventListener(type: K, listener: (this: HTMLTableSectionElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void; addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void; } @@ -6255,7 +6669,7 @@ declare var HTMLTableSectionElement: { interface HTMLTemplateElement extends HTMLElement { readonly content: DocumentFragment; - addEventListener(type: K, listener: (this: HTMLElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void; + addEventListener(type: K, listener: (this: HTMLTemplateElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void; addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void; } @@ -6362,7 +6776,7 @@ interface HTMLTextAreaElement extends HTMLElement { * @param end The offset into the text field for the end of the selection. */ setSelectionRange(start: number, end: number): void; - addEventListener(type: K, listener: (this: HTMLElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void; + addEventListener(type: K, listener: (this: HTMLTextAreaElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void; addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void; } @@ -6371,12 +6785,23 @@ declare var HTMLTextAreaElement: { new(): HTMLTextAreaElement; } +interface HTMLTimeElement extends HTMLElement { + dateTime: string; + addEventListener(type: K, listener: (this: HTMLTimeElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void; + addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void; +} + +declare var HTMLTimeElement: { + prototype: HTMLTimeElement; + new(): HTMLTimeElement; +} + interface HTMLTitleElement extends HTMLElement { /** * Retrieves or sets the text of the object as a string. */ text: string; - addEventListener(type: K, listener: (this: HTMLElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void; + addEventListener(type: K, listener: (this: HTMLTitleElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void; addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void; } @@ -6397,7 +6822,7 @@ interface HTMLTrackElement extends HTMLElement { readonly LOADED: number; readonly LOADING: number; readonly NONE: number; - addEventListener(type: K, listener: (this: HTMLElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void; + addEventListener(type: K, listener: (this: HTMLTrackElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void; addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void; } @@ -6413,7 +6838,7 @@ declare var HTMLTrackElement: { interface HTMLUListElement extends HTMLElement { compact: boolean; type: string; - addEventListener(type: K, listener: (this: HTMLElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void; + addEventListener(type: K, listener: (this: HTMLUListElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void; addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void; } @@ -6423,7 +6848,7 @@ declare var HTMLUListElement: { } interface HTMLUnknownElement extends HTMLElement { - addEventListener(type: K, listener: (this: HTMLElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void; + addEventListener(type: K, listener: (this: HTMLUnknownElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void; addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void; } @@ -6494,7 +6919,21 @@ interface HashChangeEvent extends Event { declare var HashChangeEvent: { prototype: HashChangeEvent; - new(type: string, eventInitDict?: HashChangeEventInit): HashChangeEvent; + new(typeArg: string, eventInitDict?: HashChangeEventInit): HashChangeEvent; +} + +interface Headers { + append(name: string, value: string): void; + delete(name: string): void; + forEach(callback: ForEachCallback): void; + get(name: string): string | null; + has(name: string): boolean; + set(name: string, value: string): void; +} + +declare var Headers: { + prototype: Headers; + new(init?: any): Headers; } interface History { @@ -6548,14 +6987,14 @@ declare var IDBCursorWithValue: { interface IDBDatabaseEventMap { "abort": Event; - "error": ErrorEvent; + "error": Event; } interface IDBDatabase extends EventTarget { readonly name: string; readonly objectStoreNames: DOMStringList; onabort: (this: IDBDatabase, ev: Event) => any; - onerror: (this: IDBDatabase, ev: ErrorEvent) => any; + onerror: (this: IDBDatabase, ev: Event) => any; version: number; onversionchange: (ev: IDBVersionChangeEvent) => any; close(): void; @@ -6658,13 +7097,13 @@ declare var IDBOpenDBRequest: { } interface IDBRequestEventMap { - "error": ErrorEvent; + "error": Event; "success": Event; } interface IDBRequest extends EventTarget { readonly error: DOMError; - onerror: (this: IDBRequest, ev: ErrorEvent) => any; + onerror: (this: IDBRequest, ev: Event) => any; onsuccess: (this: IDBRequest, ev: Event) => any; readonly readyState: string; readonly result: any; @@ -6682,7 +7121,7 @@ declare var IDBRequest: { interface IDBTransactionEventMap { "abort": Event; "complete": Event; - "error": ErrorEvent; + "error": Event; } interface IDBTransaction extends EventTarget { @@ -6691,7 +7130,7 @@ interface IDBTransaction extends EventTarget { readonly mode: string; onabort: (this: IDBTransaction, ev: Event) => any; oncomplete: (this: IDBTransaction, ev: Event) => any; - onerror: (this: IDBTransaction, ev: ErrorEvent) => any; + onerror: (this: IDBTransaction, ev: Event) => any; abort(): void; objectStore(name: string): IDBObjectStore; readonly READ_ONLY: string; @@ -6719,6 +7158,15 @@ declare var IDBVersionChangeEvent: { new(): IDBVersionChangeEvent; } +interface IIRFilterNode extends AudioNode { + getFrequencyResponse(frequencyHz: Float32Array, magResponse: Float32Array, phaseResponse: Float32Array): void; +} + +declare var IIRFilterNode: { + prototype: IIRFilterNode; + new(): IIRFilterNode; +} + interface ImageData { data: Uint8ClampedArray; readonly height: number; @@ -6731,6 +7179,35 @@ declare var ImageData: { new(array: Uint8ClampedArray, width: number, height: number): ImageData; } +interface IntersectionObserver { + readonly root: Element | null; + readonly rootMargin: string; + readonly thresholds: number[]; + disconnect(): void; + observe(target: Element): void; + takeRecords(): IntersectionObserverEntry[]; + unobserve(target: Element): void; +} + +declare var IntersectionObserver: { + prototype: IntersectionObserver; + new(callback: IntersectionObserverCallback, options?: IntersectionObserverInit): IntersectionObserver; +} + +interface IntersectionObserverEntry { + readonly boundingClientRect: ClientRect; + readonly intersectionRatio: number; + readonly intersectionRect: ClientRect; + readonly rootBounds: ClientRect; + readonly target: Element; + readonly time: number; +} + +declare var IntersectionObserverEntry: { + prototype: IntersectionObserverEntry; + new(intersectionObserverEntryInit: IntersectionObserverEntryInit): IntersectionObserverEntry; +} + interface KeyboardEvent extends UIEvent { readonly altKey: boolean; readonly char: string | null; @@ -6832,13 +7309,13 @@ declare var MSApp: MSApp; interface MSAppAsyncOperationEventMap { "complete": Event; - "error": ErrorEvent; + "error": Event; } interface MSAppAsyncOperation extends EventTarget { readonly error: DOMError; oncomplete: (this: MSAppAsyncOperation, ev: Event) => any; - onerror: (this: MSAppAsyncOperation, ev: ErrorEvent) => any; + onerror: (this: MSAppAsyncOperation, ev: Event) => any; readonly readyState: number; readonly result: any; start(): void; @@ -6995,12 +7472,13 @@ interface MSHTMLWebViewElement extends HTMLElement { goForward(): void; invokeScriptAsync(scriptName: string, ...args: any[]): MSWebViewAsyncOperation; navigate(uri: string): void; + navigateFocus(navigationReason: string, origin: FocusNavigationOrigin): void; navigateToLocalStreamUri(source: string, streamResolver: any): void; navigateToString(contents: string): void; navigateWithHttpRequestMessage(requestMessage: any): void; refresh(): void; stop(): void; - addEventListener(type: K, listener: (this: HTMLElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void; + addEventListener(type: K, listener: (this: MSHTMLWebViewElement, ev: HTMLElementEventMap[K]) => any, useCapture?: boolean): void; addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void; } @@ -7192,7 +7670,7 @@ interface MSStreamReader extends EventTarget, MSBaseReader { readAsBlob(stream: MSStream, size?: number): void; readAsDataURL(stream: MSStream, size?: number): void; readAsText(stream: MSStream, encoding?: string, size?: number): void; - addEventListener(type: K, listener: (this: MSBaseReader, ev: MSBaseReaderEventMap[K]) => any, useCapture?: boolean): void; + addEventListener(type: K, listener: (this: MSStreamReader, ev: MSBaseReaderEventMap[K]) => any, useCapture?: boolean): void; addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void; } @@ -7203,13 +7681,13 @@ declare var MSStreamReader: { interface MSWebViewAsyncOperationEventMap { "complete": Event; - "error": ErrorEvent; + "error": Event; } interface MSWebViewAsyncOperation extends EventTarget { readonly error: DOMError; oncomplete: (this: MSWebViewAsyncOperation, ev: Event) => any; - onerror: (this: MSWebViewAsyncOperation, ev: ErrorEvent) => any; + onerror: (this: MSWebViewAsyncOperation, ev: Event) => any; readonly readyState: number; readonly result: any; readonly target: MSHTMLWebViewElement; @@ -7419,18 +7897,18 @@ declare var MediaSource: { interface MediaStreamEventMap { "active": Event; - "addtrack": TrackEvent; + "addtrack": MediaStreamTrackEvent; "inactive": Event; - "removetrack": TrackEvent; + "removetrack": MediaStreamTrackEvent; } interface MediaStream extends EventTarget { readonly active: boolean; readonly id: string; onactive: (this: MediaStream, ev: Event) => any; - onaddtrack: (this: MediaStream, ev: TrackEvent) => any; + onaddtrack: (this: MediaStream, ev: MediaStreamTrackEvent) => any; oninactive: (this: MediaStream, ev: Event) => any; - onremovetrack: (this: MediaStream, ev: TrackEvent) => any; + onremovetrack: (this: MediaStream, ev: MediaStreamTrackEvent) => any; addTrack(track: MediaStreamTrack): void; clone(): MediaStream; getAudioTracks(): MediaStreamTrack[]; @@ -7473,7 +7951,16 @@ interface MediaStreamErrorEvent extends Event { declare var MediaStreamErrorEvent: { prototype: MediaStreamErrorEvent; - new(type: string, eventInitDict?: MediaStreamErrorEventInit): MediaStreamErrorEvent; + new(typeArg: string, eventInitDict?: MediaStreamErrorEventInit): MediaStreamErrorEvent; +} + +interface MediaStreamEvent extends Event { + readonly stream: MediaStream | null; +} + +declare var MediaStreamEvent: { + prototype: MediaStreamEvent; + new(type: string, eventInitDict: MediaStreamEventInit): MediaStreamEvent; } interface MediaStreamTrackEventMap { @@ -7517,7 +8004,7 @@ interface MediaStreamTrackEvent extends Event { declare var MediaStreamTrackEvent: { prototype: MediaStreamTrackEvent; - new(type: string, eventInitDict?: MediaStreamTrackEventInit): MediaStreamTrackEvent; + new(typeArg: string, eventInitDict?: MediaStreamTrackEventInit): MediaStreamTrackEvent; } interface MessageChannel { @@ -7550,7 +8037,7 @@ interface MessagePortEventMap { interface MessagePort extends EventTarget { onmessage: (this: MessagePort, ev: MessageEvent) => any; close(): void; - postMessage(message?: any, ports?: any): void; + postMessage(message?: any, transfer?: any[]): void; start(): void; addEventListener(type: K, listener: (this: MessagePort, ev: MessagePortEventMap[K]) => any, useCapture?: boolean): void; addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void; @@ -7712,9 +8199,10 @@ declare var NavigationEventWithReferrer: { new(): NavigationEventWithReferrer; } -interface Navigator extends Object, NavigatorID, NavigatorOnLine, NavigatorContentUtils, NavigatorStorageUtils, NavigatorGeolocation, MSNavigatorDoNotTrack, MSFileSaver, NavigatorUserMedia { - readonly appCodeName: string; +interface Navigator extends Object, NavigatorID, NavigatorOnLine, NavigatorContentUtils, NavigatorStorageUtils, NavigatorGeolocation, MSNavigatorDoNotTrack, MSFileSaver, NavigatorBeacon, NavigatorConcurrentHardware, NavigatorUserMedia { + readonly authentication: WebAuthentication; readonly cookieEnabled: boolean; + gamepadInputEmulation: string; readonly language: string; readonly maxTouchPoints: number; readonly mimeTypes: MimeTypeArray; @@ -7723,6 +8211,7 @@ interface Navigator extends Object, NavigatorID, NavigatorOnLine, NavigatorConte readonly msPointerEnabled: boolean; readonly plugins: PluginArray; readonly pointerEnabled: boolean; + readonly serviceWorker: ServiceWorkerContainer; readonly webdriver: boolean; readonly hardwareConcurrency: number; getGamepads(): Gamepad[]; @@ -7754,7 +8243,7 @@ interface Node extends EventTarget { readonly parentNode: Node | null; readonly previousSibling: Node | null; textContent: string | null; - appendChild(newChild: Node): Node; + appendChild(newChild: T): T; cloneNode(deep?: boolean): Node; compareDocumentPosition(other: Node): number; contains(child: Node): boolean; @@ -7861,6 +8350,36 @@ declare var NodeList: { new(): NodeList; } +interface NotificationEventMap { + "click": Event; + "close": Event; + "error": Event; + "show": Event; +} + +interface Notification extends EventTarget { + readonly body: string; + readonly dir: string; + readonly icon: string; + readonly lang: string; + onclick: (this: Notification, ev: Event) => any; + onclose: (this: Notification, ev: Event) => any; + onerror: (this: Notification, ev: Event) => any; + onshow: (this: Notification, ev: Event) => any; + readonly permission: string; + readonly tag: string; + readonly title: string; + close(): void; + addEventListener(type: K, listener: (this: Notification, ev: NotificationEventMap[K]) => any, useCapture?: boolean): void; + addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void; +} + +declare var Notification: { + prototype: Notification; + new(title: string, options?: NotificationOptions): Notification; + requestPermission(callback?: NotificationPermissionCallback): PromiseLike; +} + interface OES_element_index_uint { } @@ -7895,6 +8414,24 @@ declare var OES_texture_float_linear: { new(): OES_texture_float_linear; } +interface OES_texture_half_float { + readonly HALF_FLOAT_OES: number; +} + +declare var OES_texture_half_float: { + prototype: OES_texture_half_float; + new(): OES_texture_half_float; + readonly HALF_FLOAT_OES: number; +} + +interface OES_texture_half_float_linear { +} + +declare var OES_texture_half_float_linear: { + prototype: OES_texture_half_float_linear; + new(): OES_texture_half_float_linear; +} + interface OfflineAudioCompletionEvent extends Event { readonly renderedBuffer: AudioBuffer; } @@ -7904,13 +8441,15 @@ declare var OfflineAudioCompletionEvent: { new(): OfflineAudioCompletionEvent; } -interface OfflineAudioContextEventMap { - "complete": Event; +interface OfflineAudioContextEventMap extends AudioContextEventMap { + "complete": OfflineAudioCompletionEvent; } -interface OfflineAudioContext extends AudioContext { - oncomplete: (this: OfflineAudioContext, ev: Event) => any; +interface OfflineAudioContext extends AudioContextBase { + readonly length: number; + oncomplete: (this: OfflineAudioContext, ev: OfflineAudioCompletionEvent) => any; startRendering(): PromiseLike; + suspend(suspendTime: number): PromiseLike; addEventListener(type: K, listener: (this: OfflineAudioContext, ev: OfflineAudioContextEventMap[K]) => any, useCapture?: boolean): void; addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void; } @@ -7986,6 +8525,82 @@ declare var PannerNode: { new(): PannerNode; } +interface Path2D extends Object, CanvasPathMethods { +} + +declare var Path2D: { + prototype: Path2D; + new(path?: Path2D): Path2D; +} + +interface PaymentAddress { + readonly addressLine: string[]; + readonly city: string; + readonly country: string; + readonly dependentLocality: string; + readonly languageCode: string; + readonly organization: string; + readonly phone: string; + readonly postalCode: string; + readonly recipient: string; + readonly region: string; + readonly sortingCode: string; + toJSON(): any; +} + +declare var PaymentAddress: { + prototype: PaymentAddress; + new(): PaymentAddress; +} + +interface PaymentRequestEventMap { + "shippingaddresschange": Event; + "shippingoptionchange": Event; +} + +interface PaymentRequest extends EventTarget { + onshippingaddresschange: (this: PaymentRequest, ev: Event) => any; + onshippingoptionchange: (this: PaymentRequest, ev: Event) => any; + readonly shippingAddress: PaymentAddress | null; + readonly shippingOption: string | null; + readonly shippingType: string | null; + abort(): PromiseLike; + show(): PromiseLike; + addEventListener(type: K, listener: (this: PaymentRequest, ev: PaymentRequestEventMap[K]) => any, useCapture?: boolean): void; + addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void; +} + +declare var PaymentRequest: { + prototype: PaymentRequest; + new(methodData: PaymentMethodData[], details: PaymentDetails, options?: PaymentOptions): PaymentRequest; +} + +interface PaymentRequestUpdateEvent extends Event { + updateWith(d: PromiseLike): void; +} + +declare var PaymentRequestUpdateEvent: { + prototype: PaymentRequestUpdateEvent; + new(type: string, eventInitDict?: PaymentRequestUpdateEventInit): PaymentRequestUpdateEvent; +} + +interface PaymentResponse { + readonly details: any; + readonly methodName: string; + readonly payerEmail: string | null; + readonly payerName: string | null; + readonly payerPhone: string | null; + readonly shippingAddress: PaymentAddress | null; + readonly shippingOption: string | null; + complete(result?: string): PromiseLike; + toJSON(): any; +} + +declare var PaymentResponse: { + prototype: PaymentResponse; + new(): PaymentResponse; +} + interface PerfWidgetExternal { readonly activeNetworkRequestCount: number; readonly averageFrameTime: number; @@ -8251,7 +8866,7 @@ interface PopStateEvent extends Event { declare var PopStateEvent: { prototype: PopStateEvent; - new(): PopStateEvent; + new(typeArg: string, eventInitDict?: PopStateEventInit): PopStateEvent; } interface Position { @@ -8302,23 +8917,57 @@ declare var ProgressEvent: { new(type: string, eventInitDict?: ProgressEventInit): ProgressEvent; } +interface PushManager { + getSubscription(): PromiseLike; + permissionState(options?: PushSubscriptionOptionsInit): PromiseLike; + subscribe(options?: PushSubscriptionOptionsInit): PromiseLike; +} + +declare var PushManager: { + prototype: PushManager; + new(): PushManager; +} + +interface PushSubscription { + readonly endpoint: USVString; + readonly options: PushSubscriptionOptions; + getKey(name: string): ArrayBuffer | null; + toJSON(): any; + unsubscribe(): PromiseLike; +} + +declare var PushSubscription: { + prototype: PushSubscription; + new(): PushSubscription; +} + +interface PushSubscriptionOptions { + readonly applicationServerKey: ArrayBuffer | null; + readonly userVisibleOnly: boolean; +} + +declare var PushSubscriptionOptions: { + prototype: PushSubscriptionOptions; + new(): PushSubscriptionOptions; +} + interface RTCDTMFToneChangeEvent extends Event { readonly tone: string; } declare var RTCDTMFToneChangeEvent: { prototype: RTCDTMFToneChangeEvent; - new(type: string, eventInitDict: RTCDTMFToneChangeEventInit): RTCDTMFToneChangeEvent; + new(typeArg: string, eventInitDict: RTCDTMFToneChangeEventInit): RTCDTMFToneChangeEvent; } interface RTCDtlsTransportEventMap { "dtlsstatechange": RTCDtlsTransportStateChangedEvent; - "error": ErrorEvent; + "error": Event; } interface RTCDtlsTransport extends RTCStatsProvider { ondtlsstatechange: ((this: RTCDtlsTransport, ev: RTCDtlsTransportStateChangedEvent) => any) | null; - onerror: ((this: RTCDtlsTransport, ev: ErrorEvent) => any) | null; + onerror: ((this: RTCDtlsTransport, ev: Event) => any) | null; readonly state: string; readonly transport: RTCIceTransport; getLocalParameters(): RTCDtlsParameters; @@ -8365,6 +9014,18 @@ declare var RTCDtmfSender: { new(sender: RTCRtpSender): RTCDtmfSender; } +interface RTCIceCandidate { + candidate: string | null; + sdpMLineIndex: number | null; + sdpMid: string | null; + toJSON(): any; +} + +declare var RTCIceCandidate: { + prototype: RTCIceCandidate; + new(candidateInitDict?: RTCIceCandidateInit): RTCIceCandidate; +} + interface RTCIceCandidatePairChangedEvent extends Event { readonly pair: RTCIceCandidatePair; } @@ -8375,16 +9036,16 @@ declare var RTCIceCandidatePairChangedEvent: { } interface RTCIceGathererEventMap { - "error": ErrorEvent; + "error": Event; "localcandidate": RTCIceGathererEvent; } interface RTCIceGatherer extends RTCStatsProvider { readonly component: string; - onerror: ((this: RTCIceGatherer, ev: ErrorEvent) => any) | null; + onerror: ((this: RTCIceGatherer, ev: Event) => any) | null; onlocalcandidate: ((this: RTCIceGatherer, ev: RTCIceGathererEvent) => any) | null; createAssociatedGatherer(): RTCIceGatherer; - getLocalCandidates(): RTCIceCandidate[]; + getLocalCandidates(): RTCIceCandidateDictionary[]; getLocalParameters(): RTCIceParameters; addEventListener(type: K, listener: (this: RTCIceGatherer, ev: RTCIceGathererEventMap[K]) => any, useCapture?: boolean): void; addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void; @@ -8396,7 +9057,7 @@ declare var RTCIceGatherer: { } interface RTCIceGathererEvent extends Event { - readonly candidate: RTCIceCandidate | RTCIceCandidateComplete; + readonly candidate: RTCIceCandidateDictionary | RTCIceCandidateComplete; } declare var RTCIceGathererEvent: { @@ -8416,12 +9077,12 @@ interface RTCIceTransport extends RTCStatsProvider { onicestatechange: ((this: RTCIceTransport, ev: RTCIceTransportStateChangedEvent) => any) | null; readonly role: string; readonly state: string; - addRemoteCandidate(remoteCandidate: RTCIceCandidate | RTCIceCandidateComplete): void; + addRemoteCandidate(remoteCandidate: RTCIceCandidateDictionary | RTCIceCandidateComplete): void; createAssociatedTransport(): RTCIceTransport; getNominatedCandidatePair(): RTCIceCandidatePair | null; - getRemoteCandidates(): RTCIceCandidate[]; + getRemoteCandidates(): RTCIceCandidateDictionary[]; getRemoteParameters(): RTCIceParameters | null; - setRemoteCandidates(remoteCandidates: RTCIceCandidate[]): void; + setRemoteCandidates(remoteCandidates: RTCIceCandidateDictionary[]): void; start(gatherer: RTCIceGatherer, remoteParameters: RTCIceParameters, role?: string): void; stop(): void; addEventListener(type: K, listener: (this: RTCIceTransport, ev: RTCIceTransportEventMap[K]) => any, useCapture?: boolean): void; @@ -8442,12 +9103,67 @@ declare var RTCIceTransportStateChangedEvent: { new(): RTCIceTransportStateChangedEvent; } +interface RTCPeerConnectionEventMap { + "addstream": MediaStreamEvent; + "icecandidate": RTCPeerConnectionIceEvent; + "iceconnectionstatechange": Event; + "icegatheringstatechange": Event; + "negotiationneeded": Event; + "removestream": MediaStreamEvent; + "signalingstatechange": Event; +} + +interface RTCPeerConnection extends EventTarget { + readonly canTrickleIceCandidates: boolean | null; + readonly iceConnectionState: string; + readonly iceGatheringState: string; + readonly localDescription: RTCSessionDescription | null; + onaddstream: (this: RTCPeerConnection, ev: MediaStreamEvent) => any; + onicecandidate: (this: RTCPeerConnection, ev: RTCPeerConnectionIceEvent) => any; + oniceconnectionstatechange: (this: RTCPeerConnection, ev: Event) => any; + onicegatheringstatechange: (this: RTCPeerConnection, ev: Event) => any; + onnegotiationneeded: (this: RTCPeerConnection, ev: Event) => any; + onremovestream: (this: RTCPeerConnection, ev: MediaStreamEvent) => any; + onsignalingstatechange: (this: RTCPeerConnection, ev: Event) => any; + readonly remoteDescription: RTCSessionDescription | null; + readonly signalingState: string; + addIceCandidate(candidate: RTCIceCandidate, successCallback?: VoidFunction, failureCallback?: RTCPeerConnectionErrorCallback): PromiseLike; + addStream(stream: MediaStream): void; + close(): void; + createAnswer(successCallback?: RTCSessionDescriptionCallback, failureCallback?: RTCPeerConnectionErrorCallback): PromiseLike; + createOffer(successCallback?: RTCSessionDescriptionCallback, failureCallback?: RTCPeerConnectionErrorCallback, options?: RTCOfferOptions): PromiseLike; + getConfiguration(): RTCConfiguration; + getLocalStreams(): MediaStream[]; + getRemoteStreams(): MediaStream[]; + getStats(selector: MediaStreamTrack | null, successCallback?: RTCStatsCallback, failureCallback?: RTCPeerConnectionErrorCallback): PromiseLike; + getStreamById(streamId: string): MediaStream | null; + removeStream(stream: MediaStream): void; + setLocalDescription(description: RTCSessionDescription, successCallback?: VoidFunction, failureCallback?: RTCPeerConnectionErrorCallback): PromiseLike; + setRemoteDescription(description: RTCSessionDescription, successCallback?: VoidFunction, failureCallback?: RTCPeerConnectionErrorCallback): PromiseLike; + addEventListener(type: K, listener: (this: RTCPeerConnection, ev: RTCPeerConnectionEventMap[K]) => any, useCapture?: boolean): void; + addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void; +} + +declare var RTCPeerConnection: { + prototype: RTCPeerConnection; + new(configuration: RTCConfiguration): RTCPeerConnection; +} + +interface RTCPeerConnectionIceEvent extends Event { + readonly candidate: RTCIceCandidate; +} + +declare var RTCPeerConnectionIceEvent: { + prototype: RTCPeerConnectionIceEvent; + new(type: string, eventInitDict: RTCPeerConnectionIceEventInit): RTCPeerConnectionIceEvent; +} + interface RTCRtpReceiverEventMap { - "error": ErrorEvent; + "error": Event; } interface RTCRtpReceiver extends RTCStatsProvider { - onerror: ((this: RTCRtpReceiver, ev: ErrorEvent) => any) | null; + onerror: ((this: RTCRtpReceiver, ev: Event) => any) | null; readonly rtcpTransport: RTCDtlsTransport; readonly track: MediaStreamTrack | null; readonly transport: RTCDtlsTransport | RTCSrtpSdesTransport; @@ -8467,12 +9183,12 @@ declare var RTCRtpReceiver: { } interface RTCRtpSenderEventMap { - "error": ErrorEvent; + "error": Event; "ssrcconflict": RTCSsrcConflictEvent; } interface RTCRtpSender extends RTCStatsProvider { - onerror: ((this: RTCRtpSender, ev: ErrorEvent) => any) | null; + onerror: ((this: RTCRtpSender, ev: Event) => any) | null; onssrcconflict: ((this: RTCRtpSender, ev: RTCSsrcConflictEvent) => any) | null; readonly rtcpTransport: RTCDtlsTransport; readonly track: MediaStreamTrack; @@ -8491,12 +9207,23 @@ declare var RTCRtpSender: { getCapabilities(kind?: string): RTCRtpCapabilities; } +interface RTCSessionDescription { + sdp: string | null; + type: string | null; + toJSON(): any; +} + +declare var RTCSessionDescription: { + prototype: RTCSessionDescription; + new(descriptionInitDict?: RTCSessionDescriptionInit): RTCSessionDescription; +} + interface RTCSrtpSdesTransportEventMap { - "error": ErrorEvent; + "error": Event; } interface RTCSrtpSdesTransport extends EventTarget { - onerror: ((this: RTCSrtpSdesTransport, ev: ErrorEvent) => any) | null; + onerror: ((this: RTCSrtpSdesTransport, ev: Event) => any) | null; readonly transport: RTCIceTransport; addEventListener(type: K, listener: (this: RTCSrtpSdesTransport, ev: RTCSrtpSdesTransportEventMap[K]) => any, useCapture?: boolean): void; addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void; @@ -8571,9 +9298,69 @@ declare var Range: { readonly START_TO_START: number; } -interface SVGAElement extends SVGElement, SVGStylable, SVGTransformable, SVGTests, SVGLangSpace, SVGExternalResourcesRequired, SVGURIReference { +interface ReadableStream { + readonly locked: boolean; + cancel(): PromiseLike; + getReader(): ReadableStreamReader; +} + +declare var ReadableStream: { + prototype: ReadableStream; + new(): ReadableStream; +} + +interface ReadableStreamReader { + cancel(): PromiseLike; + read(): PromiseLike; + releaseLock(): void; +} + +declare var ReadableStreamReader: { + prototype: ReadableStreamReader; + new(): ReadableStreamReader; +} + +interface Request extends Object, Body { + readonly cache: string; + readonly credentials: string; + readonly destination: string; + readonly headers: Headers; + readonly integrity: string; + readonly keepalive: boolean; + readonly method: string; + readonly mode: string; + readonly redirect: string; + readonly referrer: string; + readonly referrerPolicy: string; + readonly type: string; + readonly url: string; + clone(): Request; +} + +declare var Request: { + prototype: Request; + new(input: Request | string, init?: RequestInit): Request; +} + +interface Response extends Object, Body { + readonly body: ReadableStream | null; + readonly headers: Headers; + readonly ok: boolean; + readonly status: number; + readonly statusText: string; + readonly type: string; + readonly url: string; + clone(): Response; +} + +declare var Response: { + prototype: Response; + new(body?: any, init?: ResponseInit): Response; +} + +interface SVGAElement extends SVGGraphicsElement, SVGURIReference { readonly target: SVGAnimatedString; - addEventListener(type: K, listener: (this: SVGElement, ev: SVGElementEventMap[K]) => any, useCapture?: boolean): void; + addEventListener(type: K, listener: (this: SVGAElement, ev: SVGElementEventMap[K]) => any, useCapture?: boolean): void; addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void; } @@ -8726,11 +9513,11 @@ declare var SVGAnimatedTransformList: { new(): SVGAnimatedTransformList; } -interface SVGCircleElement extends SVGElement, SVGStylable, SVGTransformable, SVGTests, SVGLangSpace, SVGExternalResourcesRequired { +interface SVGCircleElement extends SVGGraphicsElement { readonly cx: SVGAnimatedLength; readonly cy: SVGAnimatedLength; readonly r: SVGAnimatedLength; - addEventListener(type: K, listener: (this: SVGElement, ev: SVGElementEventMap[K]) => any, useCapture?: boolean): void; + addEventListener(type: K, listener: (this: SVGCircleElement, ev: SVGElementEventMap[K]) => any, useCapture?: boolean): void; addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void; } @@ -8739,9 +9526,9 @@ declare var SVGCircleElement: { new(): SVGCircleElement; } -interface SVGClipPathElement extends SVGElement, SVGStylable, SVGTransformable, SVGTests, SVGLangSpace, SVGExternalResourcesRequired, SVGUnitTypes { +interface SVGClipPathElement extends SVGGraphicsElement, SVGUnitTypes { readonly clipPathUnits: SVGAnimatedEnumeration; - addEventListener(type: K, listener: (this: SVGElement, ev: SVGElementEventMap[K]) => any, useCapture?: boolean): void; + addEventListener(type: K, listener: (this: SVGClipPathElement, ev: SVGElementEventMap[K]) => any, useCapture?: boolean): void; addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void; } @@ -8764,7 +9551,7 @@ interface SVGComponentTransferFunctionElement extends SVGElement { readonly SVG_FECOMPONENTTRANSFER_TYPE_LINEAR: number; readonly SVG_FECOMPONENTTRANSFER_TYPE_TABLE: number; readonly SVG_FECOMPONENTTRANSFER_TYPE_UNKNOWN: number; - addEventListener(type: K, listener: (this: SVGElement, ev: SVGElementEventMap[K]) => any, useCapture?: boolean): void; + addEventListener(type: K, listener: (this: SVGComponentTransferFunctionElement, ev: SVGElementEventMap[K]) => any, useCapture?: boolean): void; addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void; } @@ -8779,8 +9566,8 @@ declare var SVGComponentTransferFunctionElement: { readonly SVG_FECOMPONENTTRANSFER_TYPE_UNKNOWN: number; } -interface SVGDefsElement extends SVGElement, SVGStylable, SVGTransformable, SVGTests, SVGLangSpace, SVGExternalResourcesRequired { - addEventListener(type: K, listener: (this: SVGElement, ev: SVGElementEventMap[K]) => any, useCapture?: boolean): void; +interface SVGDefsElement extends SVGGraphicsElement { + addEventListener(type: K, listener: (this: SVGDefsElement, ev: SVGElementEventMap[K]) => any, useCapture?: boolean): void; addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void; } @@ -8789,8 +9576,8 @@ declare var SVGDefsElement: { new(): SVGDefsElement; } -interface SVGDescElement extends SVGElement, SVGStylable, SVGLangSpace { - addEventListener(type: K, listener: (this: SVGElement, ev: SVGElementEventMap[K]) => any, useCapture?: boolean): void; +interface SVGDescElement extends SVGElement { + addEventListener(type: K, listener: (this: SVGDescElement, ev: SVGElementEventMap[K]) => any, useCapture?: boolean): void; addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void; } @@ -8813,6 +9600,7 @@ interface SVGElementEventMap extends ElementEventMap { } interface SVGElement extends Element { + className: any; onclick: (this: SVGElement, ev: MouseEvent) => any; ondblclick: (this: SVGElement, ev: MouseEvent) => any; onfocusin: (this: SVGElement, ev: FocusEvent) => any; @@ -8824,9 +9612,9 @@ interface SVGElement extends Element { onmouseover: (this: SVGElement, ev: MouseEvent) => any; onmouseup: (this: SVGElement, ev: MouseEvent) => any; readonly ownerSVGElement: SVGSVGElement; + readonly style: CSSStyleDeclaration; readonly viewportElement: SVGElement; xmlbase: string; - className: any; addEventListener(type: K, listener: (this: SVGElement, ev: SVGElementEventMap[K]) => any, useCapture?: boolean): void; addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void; } @@ -8862,12 +9650,12 @@ declare var SVGElementInstanceList: { new(): SVGElementInstanceList; } -interface SVGEllipseElement extends SVGElement, SVGStylable, SVGTransformable, SVGTests, SVGLangSpace, SVGExternalResourcesRequired { +interface SVGEllipseElement extends SVGGraphicsElement { readonly cx: SVGAnimatedLength; readonly cy: SVGAnimatedLength; readonly rx: SVGAnimatedLength; readonly ry: SVGAnimatedLength; - addEventListener(type: K, listener: (this: SVGElement, ev: SVGElementEventMap[K]) => any, useCapture?: boolean): void; + addEventListener(type: K, listener: (this: SVGEllipseElement, ev: SVGElementEventMap[K]) => any, useCapture?: boolean): void; addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void; } @@ -8897,7 +9685,7 @@ interface SVGFEBlendElement extends SVGElement, SVGFilterPrimitiveStandardAttrib readonly SVG_FEBLEND_MODE_SCREEN: number; readonly SVG_FEBLEND_MODE_SOFT_LIGHT: number; readonly SVG_FEBLEND_MODE_UNKNOWN: number; - addEventListener(type: K, listener: (this: SVGElement, ev: SVGElementEventMap[K]) => any, useCapture?: boolean): void; + addEventListener(type: K, listener: (this: SVGFEBlendElement, ev: SVGElementEventMap[K]) => any, useCapture?: boolean): void; addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void; } @@ -8932,7 +9720,7 @@ interface SVGFEColorMatrixElement extends SVGElement, SVGFilterPrimitiveStandard readonly SVG_FECOLORMATRIX_TYPE_MATRIX: number; readonly SVG_FECOLORMATRIX_TYPE_SATURATE: number; readonly SVG_FECOLORMATRIX_TYPE_UNKNOWN: number; - addEventListener(type: K, listener: (this: SVGElement, ev: SVGElementEventMap[K]) => any, useCapture?: boolean): void; + addEventListener(type: K, listener: (this: SVGFEColorMatrixElement, ev: SVGElementEventMap[K]) => any, useCapture?: boolean): void; addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void; } @@ -8948,7 +9736,7 @@ declare var SVGFEColorMatrixElement: { interface SVGFEComponentTransferElement extends SVGElement, SVGFilterPrimitiveStandardAttributes { readonly in1: SVGAnimatedString; - addEventListener(type: K, listener: (this: SVGElement, ev: SVGElementEventMap[K]) => any, useCapture?: boolean): void; + addEventListener(type: K, listener: (this: SVGFEComponentTransferElement, ev: SVGElementEventMap[K]) => any, useCapture?: boolean): void; addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void; } @@ -8972,7 +9760,7 @@ interface SVGFECompositeElement extends SVGElement, SVGFilterPrimitiveStandardAt readonly SVG_FECOMPOSITE_OPERATOR_OVER: number; readonly SVG_FECOMPOSITE_OPERATOR_UNKNOWN: number; readonly SVG_FECOMPOSITE_OPERATOR_XOR: number; - addEventListener(type: K, listener: (this: SVGElement, ev: SVGElementEventMap[K]) => any, useCapture?: boolean): void; + addEventListener(type: K, listener: (this: SVGFECompositeElement, ev: SVGElementEventMap[K]) => any, useCapture?: boolean): void; addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void; } @@ -9005,7 +9793,7 @@ interface SVGFEConvolveMatrixElement extends SVGElement, SVGFilterPrimitiveStand readonly SVG_EDGEMODE_NONE: number; readonly SVG_EDGEMODE_UNKNOWN: number; readonly SVG_EDGEMODE_WRAP: number; - addEventListener(type: K, listener: (this: SVGElement, ev: SVGElementEventMap[K]) => any, useCapture?: boolean): void; + addEventListener(type: K, listener: (this: SVGFEConvolveMatrixElement, ev: SVGElementEventMap[K]) => any, useCapture?: boolean): void; addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void; } @@ -9024,7 +9812,7 @@ interface SVGFEDiffuseLightingElement extends SVGElement, SVGFilterPrimitiveStan readonly kernelUnitLengthX: SVGAnimatedNumber; readonly kernelUnitLengthY: SVGAnimatedNumber; readonly surfaceScale: SVGAnimatedNumber; - addEventListener(type: K, listener: (this: SVGElement, ev: SVGElementEventMap[K]) => any, useCapture?: boolean): void; + addEventListener(type: K, listener: (this: SVGFEDiffuseLightingElement, ev: SVGElementEventMap[K]) => any, useCapture?: boolean): void; addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void; } @@ -9044,7 +9832,7 @@ interface SVGFEDisplacementMapElement extends SVGElement, SVGFilterPrimitiveStan readonly SVG_CHANNEL_G: number; readonly SVG_CHANNEL_R: number; readonly SVG_CHANNEL_UNKNOWN: number; - addEventListener(type: K, listener: (this: SVGElement, ev: SVGElementEventMap[K]) => any, useCapture?: boolean): void; + addEventListener(type: K, listener: (this: SVGFEDisplacementMapElement, ev: SVGElementEventMap[K]) => any, useCapture?: boolean): void; addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void; } @@ -9061,7 +9849,7 @@ declare var SVGFEDisplacementMapElement: { interface SVGFEDistantLightElement extends SVGElement { readonly azimuth: SVGAnimatedNumber; readonly elevation: SVGAnimatedNumber; - addEventListener(type: K, listener: (this: SVGElement, ev: SVGElementEventMap[K]) => any, useCapture?: boolean): void; + addEventListener(type: K, listener: (this: SVGFEDistantLightElement, ev: SVGElementEventMap[K]) => any, useCapture?: boolean): void; addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void; } @@ -9071,7 +9859,7 @@ declare var SVGFEDistantLightElement: { } interface SVGFEFloodElement extends SVGElement, SVGFilterPrimitiveStandardAttributes { - addEventListener(type: K, listener: (this: SVGElement, ev: SVGElementEventMap[K]) => any, useCapture?: boolean): void; + addEventListener(type: K, listener: (this: SVGFEFloodElement, ev: SVGElementEventMap[K]) => any, useCapture?: boolean): void; addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void; } @@ -9081,6 +9869,8 @@ declare var SVGFEFloodElement: { } interface SVGFEFuncAElement extends SVGComponentTransferFunctionElement { + addEventListener(type: K, listener: (this: SVGFEFuncAElement, ev: SVGElementEventMap[K]) => any, useCapture?: boolean): void; + addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void; } declare var SVGFEFuncAElement: { @@ -9089,6 +9879,8 @@ declare var SVGFEFuncAElement: { } interface SVGFEFuncBElement extends SVGComponentTransferFunctionElement { + addEventListener(type: K, listener: (this: SVGFEFuncBElement, ev: SVGElementEventMap[K]) => any, useCapture?: boolean): void; + addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void; } declare var SVGFEFuncBElement: { @@ -9097,6 +9889,8 @@ declare var SVGFEFuncBElement: { } interface SVGFEFuncGElement extends SVGComponentTransferFunctionElement { + addEventListener(type: K, listener: (this: SVGFEFuncGElement, ev: SVGElementEventMap[K]) => any, useCapture?: boolean): void; + addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void; } declare var SVGFEFuncGElement: { @@ -9105,6 +9899,8 @@ declare var SVGFEFuncGElement: { } interface SVGFEFuncRElement extends SVGComponentTransferFunctionElement { + addEventListener(type: K, listener: (this: SVGFEFuncRElement, ev: SVGElementEventMap[K]) => any, useCapture?: boolean): void; + addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void; } declare var SVGFEFuncRElement: { @@ -9117,7 +9913,7 @@ interface SVGFEGaussianBlurElement extends SVGElement, SVGFilterPrimitiveStandar readonly stdDeviationX: SVGAnimatedNumber; readonly stdDeviationY: SVGAnimatedNumber; setStdDeviation(stdDeviationX: number, stdDeviationY: number): void; - addEventListener(type: K, listener: (this: SVGElement, ev: SVGElementEventMap[K]) => any, useCapture?: boolean): void; + addEventListener(type: K, listener: (this: SVGFEGaussianBlurElement, ev: SVGElementEventMap[K]) => any, useCapture?: boolean): void; addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void; } @@ -9126,9 +9922,9 @@ declare var SVGFEGaussianBlurElement: { new(): SVGFEGaussianBlurElement; } -interface SVGFEImageElement extends SVGElement, SVGFilterPrimitiveStandardAttributes, SVGLangSpace, SVGURIReference, SVGExternalResourcesRequired { +interface SVGFEImageElement extends SVGElement, SVGFilterPrimitiveStandardAttributes, SVGURIReference { readonly preserveAspectRatio: SVGAnimatedPreserveAspectRatio; - addEventListener(type: K, listener: (this: SVGElement, ev: SVGElementEventMap[K]) => any, useCapture?: boolean): void; + addEventListener(type: K, listener: (this: SVGFEImageElement, ev: SVGElementEventMap[K]) => any, useCapture?: boolean): void; addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void; } @@ -9138,7 +9934,7 @@ declare var SVGFEImageElement: { } interface SVGFEMergeElement extends SVGElement, SVGFilterPrimitiveStandardAttributes { - addEventListener(type: K, listener: (this: SVGElement, ev: SVGElementEventMap[K]) => any, useCapture?: boolean): void; + addEventListener(type: K, listener: (this: SVGFEMergeElement, ev: SVGElementEventMap[K]) => any, useCapture?: boolean): void; addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void; } @@ -9149,7 +9945,7 @@ declare var SVGFEMergeElement: { interface SVGFEMergeNodeElement extends SVGElement { readonly in1: SVGAnimatedString; - addEventListener(type: K, listener: (this: SVGElement, ev: SVGElementEventMap[K]) => any, useCapture?: boolean): void; + addEventListener(type: K, listener: (this: SVGFEMergeNodeElement, ev: SVGElementEventMap[K]) => any, useCapture?: boolean): void; addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void; } @@ -9166,7 +9962,7 @@ interface SVGFEMorphologyElement extends SVGElement, SVGFilterPrimitiveStandardA readonly SVG_MORPHOLOGY_OPERATOR_DILATE: number; readonly SVG_MORPHOLOGY_OPERATOR_ERODE: number; readonly SVG_MORPHOLOGY_OPERATOR_UNKNOWN: number; - addEventListener(type: K, listener: (this: SVGElement, ev: SVGElementEventMap[K]) => any, useCapture?: boolean): void; + addEventListener(type: K, listener: (this: SVGFEMorphologyElement, ev: SVGElementEventMap[K]) => any, useCapture?: boolean): void; addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void; } @@ -9182,7 +9978,7 @@ interface SVGFEOffsetElement extends SVGElement, SVGFilterPrimitiveStandardAttri readonly dx: SVGAnimatedNumber; readonly dy: SVGAnimatedNumber; readonly in1: SVGAnimatedString; - addEventListener(type: K, listener: (this: SVGElement, ev: SVGElementEventMap[K]) => any, useCapture?: boolean): void; + addEventListener(type: K, listener: (this: SVGFEOffsetElement, ev: SVGElementEventMap[K]) => any, useCapture?: boolean): void; addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void; } @@ -9195,7 +9991,7 @@ interface SVGFEPointLightElement extends SVGElement { readonly x: SVGAnimatedNumber; readonly y: SVGAnimatedNumber; readonly z: SVGAnimatedNumber; - addEventListener(type: K, listener: (this: SVGElement, ev: SVGElementEventMap[K]) => any, useCapture?: boolean): void; + addEventListener(type: K, listener: (this: SVGFEPointLightElement, ev: SVGElementEventMap[K]) => any, useCapture?: boolean): void; addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void; } @@ -9211,7 +10007,7 @@ interface SVGFESpecularLightingElement extends SVGElement, SVGFilterPrimitiveSta readonly specularConstant: SVGAnimatedNumber; readonly specularExponent: SVGAnimatedNumber; readonly surfaceScale: SVGAnimatedNumber; - addEventListener(type: K, listener: (this: SVGElement, ev: SVGElementEventMap[K]) => any, useCapture?: boolean): void; + addEventListener(type: K, listener: (this: SVGFESpecularLightingElement, ev: SVGElementEventMap[K]) => any, useCapture?: boolean): void; addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void; } @@ -9229,7 +10025,7 @@ interface SVGFESpotLightElement extends SVGElement { readonly x: SVGAnimatedNumber; readonly y: SVGAnimatedNumber; readonly z: SVGAnimatedNumber; - addEventListener(type: K, listener: (this: SVGElement, ev: SVGElementEventMap[K]) => any, useCapture?: boolean): void; + addEventListener(type: K, listener: (this: SVGFESpotLightElement, ev: SVGElementEventMap[K]) => any, useCapture?: boolean): void; addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void; } @@ -9240,7 +10036,7 @@ declare var SVGFESpotLightElement: { interface SVGFETileElement extends SVGElement, SVGFilterPrimitiveStandardAttributes { readonly in1: SVGAnimatedString; - addEventListener(type: K, listener: (this: SVGElement, ev: SVGElementEventMap[K]) => any, useCapture?: boolean): void; + addEventListener(type: K, listener: (this: SVGFETileElement, ev: SVGElementEventMap[K]) => any, useCapture?: boolean): void; addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void; } @@ -9262,7 +10058,7 @@ interface SVGFETurbulenceElement extends SVGElement, SVGFilterPrimitiveStandardA readonly SVG_TURBULENCE_TYPE_FRACTALNOISE: number; readonly SVG_TURBULENCE_TYPE_TURBULENCE: number; readonly SVG_TURBULENCE_TYPE_UNKNOWN: number; - addEventListener(type: K, listener: (this: SVGElement, ev: SVGElementEventMap[K]) => any, useCapture?: boolean): void; + addEventListener(type: K, listener: (this: SVGFETurbulenceElement, ev: SVGElementEventMap[K]) => any, useCapture?: boolean): void; addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void; } @@ -9277,7 +10073,7 @@ declare var SVGFETurbulenceElement: { readonly SVG_TURBULENCE_TYPE_UNKNOWN: number; } -interface SVGFilterElement extends SVGElement, SVGUnitTypes, SVGStylable, SVGLangSpace, SVGURIReference, SVGExternalResourcesRequired { +interface SVGFilterElement extends SVGElement, SVGUnitTypes, SVGURIReference { readonly filterResX: SVGAnimatedInteger; readonly filterResY: SVGAnimatedInteger; readonly filterUnits: SVGAnimatedEnumeration; @@ -9287,7 +10083,7 @@ interface SVGFilterElement extends SVGElement, SVGUnitTypes, SVGStylable, SVGLan readonly x: SVGAnimatedLength; readonly y: SVGAnimatedLength; setFilterRes(filterResX: number, filterResY: number): void; - addEventListener(type: K, listener: (this: SVGElement, ev: SVGElementEventMap[K]) => any, useCapture?: boolean): void; + addEventListener(type: K, listener: (this: SVGFilterElement, ev: SVGElementEventMap[K]) => any, useCapture?: boolean): void; addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void; } @@ -9296,12 +10092,12 @@ declare var SVGFilterElement: { new(): SVGFilterElement; } -interface SVGForeignObjectElement extends SVGElement, SVGStylable, SVGTransformable, SVGTests, SVGLangSpace, SVGExternalResourcesRequired { +interface SVGForeignObjectElement extends SVGGraphicsElement { readonly height: SVGAnimatedLength; readonly width: SVGAnimatedLength; readonly x: SVGAnimatedLength; readonly y: SVGAnimatedLength; - addEventListener(type: K, listener: (this: SVGElement, ev: SVGElementEventMap[K]) => any, useCapture?: boolean): void; + addEventListener(type: K, listener: (this: SVGForeignObjectElement, ev: SVGElementEventMap[K]) => any, useCapture?: boolean): void; addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void; } @@ -9310,8 +10106,8 @@ declare var SVGForeignObjectElement: { new(): SVGForeignObjectElement; } -interface SVGGElement extends SVGElement, SVGStylable, SVGTransformable, SVGTests, SVGLangSpace, SVGExternalResourcesRequired { - addEventListener(type: K, listener: (this: SVGElement, ev: SVGElementEventMap[K]) => any, useCapture?: boolean): void; +interface SVGGElement extends SVGGraphicsElement { + addEventListener(type: K, listener: (this: SVGGElement, ev: SVGElementEventMap[K]) => any, useCapture?: boolean): void; addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void; } @@ -9320,7 +10116,7 @@ declare var SVGGElement: { new(): SVGGElement; } -interface SVGGradientElement extends SVGElement, SVGStylable, SVGExternalResourcesRequired, SVGURIReference, SVGUnitTypes { +interface SVGGradientElement extends SVGElement, SVGUnitTypes, SVGURIReference { readonly gradientTransform: SVGAnimatedTransformList; readonly gradientUnits: SVGAnimatedEnumeration; readonly spreadMethod: SVGAnimatedEnumeration; @@ -9328,7 +10124,7 @@ interface SVGGradientElement extends SVGElement, SVGStylable, SVGExternalResourc readonly SVG_SPREADMETHOD_REFLECT: number; readonly SVG_SPREADMETHOD_REPEAT: number; readonly SVG_SPREADMETHOD_UNKNOWN: number; - addEventListener(type: K, listener: (this: SVGElement, ev: SVGElementEventMap[K]) => any, useCapture?: boolean): void; + addEventListener(type: K, listener: (this: SVGGradientElement, ev: SVGElementEventMap[K]) => any, useCapture?: boolean): void; addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void; } @@ -9341,13 +10137,30 @@ declare var SVGGradientElement: { readonly SVG_SPREADMETHOD_UNKNOWN: number; } -interface SVGImageElement extends SVGElement, SVGStylable, SVGTransformable, SVGTests, SVGLangSpace, SVGExternalResourcesRequired, SVGURIReference { +interface SVGGraphicsElement extends SVGElement, SVGTests { + readonly farthestViewportElement: SVGElement; + readonly nearestViewportElement: SVGElement; + readonly transform: SVGAnimatedTransformList; + getBBox(): SVGRect; + getCTM(): SVGMatrix; + getScreenCTM(): SVGMatrix; + getTransformToElement(element: SVGElement): SVGMatrix; + addEventListener(type: K, listener: (this: SVGGraphicsElement, ev: SVGElementEventMap[K]) => any, useCapture?: boolean): void; + addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void; +} + +declare var SVGGraphicsElement: { + prototype: SVGGraphicsElement; + new(): SVGGraphicsElement; +} + +interface SVGImageElement extends SVGGraphicsElement, SVGURIReference { readonly height: SVGAnimatedLength; readonly preserveAspectRatio: SVGAnimatedPreserveAspectRatio; readonly width: SVGAnimatedLength; readonly x: SVGAnimatedLength; readonly y: SVGAnimatedLength; - addEventListener(type: K, listener: (this: SVGElement, ev: SVGElementEventMap[K]) => any, useCapture?: boolean): void; + addEventListener(type: K, listener: (this: SVGImageElement, ev: SVGElementEventMap[K]) => any, useCapture?: boolean): void; addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void; } @@ -9408,12 +10221,12 @@ declare var SVGLengthList: { new(): SVGLengthList; } -interface SVGLineElement extends SVGElement, SVGStylable, SVGTransformable, SVGTests, SVGLangSpace, SVGExternalResourcesRequired { +interface SVGLineElement extends SVGGraphicsElement { readonly x1: SVGAnimatedLength; readonly x2: SVGAnimatedLength; readonly y1: SVGAnimatedLength; readonly y2: SVGAnimatedLength; - addEventListener(type: K, listener: (this: SVGElement, ev: SVGElementEventMap[K]) => any, useCapture?: boolean): void; + addEventListener(type: K, listener: (this: SVGLineElement, ev: SVGElementEventMap[K]) => any, useCapture?: boolean): void; addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void; } @@ -9427,6 +10240,8 @@ interface SVGLinearGradientElement extends SVGGradientElement { readonly x2: SVGAnimatedLength; readonly y1: SVGAnimatedLength; readonly y2: SVGAnimatedLength; + addEventListener(type: K, listener: (this: SVGLinearGradientElement, ev: SVGElementEventMap[K]) => any, useCapture?: boolean): void; + addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void; } declare var SVGLinearGradientElement: { @@ -9434,7 +10249,7 @@ declare var SVGLinearGradientElement: { new(): SVGLinearGradientElement; } -interface SVGMarkerElement extends SVGElement, SVGStylable, SVGLangSpace, SVGExternalResourcesRequired, SVGFitToViewBox { +interface SVGMarkerElement extends SVGElement, SVGFitToViewBox { readonly markerHeight: SVGAnimatedLength; readonly markerUnits: SVGAnimatedEnumeration; readonly markerWidth: SVGAnimatedLength; @@ -9450,7 +10265,7 @@ interface SVGMarkerElement extends SVGElement, SVGStylable, SVGLangSpace, SVGExt readonly SVG_MARKER_ORIENT_ANGLE: number; readonly SVG_MARKER_ORIENT_AUTO: number; readonly SVG_MARKER_ORIENT_UNKNOWN: number; - addEventListener(type: K, listener: (this: SVGElement, ev: SVGElementEventMap[K]) => any, useCapture?: boolean): void; + addEventListener(type: K, listener: (this: SVGMarkerElement, ev: SVGElementEventMap[K]) => any, useCapture?: boolean): void; addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void; } @@ -9465,14 +10280,14 @@ declare var SVGMarkerElement: { readonly SVG_MARKER_ORIENT_UNKNOWN: number; } -interface SVGMaskElement extends SVGElement, SVGStylable, SVGTests, SVGLangSpace, SVGExternalResourcesRequired, SVGUnitTypes { +interface SVGMaskElement extends SVGElement, SVGTests, SVGUnitTypes { readonly height: SVGAnimatedLength; readonly maskContentUnits: SVGAnimatedEnumeration; readonly maskUnits: SVGAnimatedEnumeration; readonly width: SVGAnimatedLength; readonly x: SVGAnimatedLength; readonly y: SVGAnimatedLength; - addEventListener(type: K, listener: (this: SVGElement, ev: SVGElementEventMap[K]) => any, useCapture?: boolean): void; + addEventListener(type: K, listener: (this: SVGMaskElement, ev: SVGElementEventMap[K]) => any, useCapture?: boolean): void; addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void; } @@ -9507,7 +10322,7 @@ declare var SVGMatrix: { } interface SVGMetadataElement extends SVGElement { - addEventListener(type: K, listener: (this: SVGElement, ev: SVGElementEventMap[K]) => any, useCapture?: boolean): void; + addEventListener(type: K, listener: (this: SVGMetadataElement, ev: SVGElementEventMap[K]) => any, useCapture?: boolean): void; addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void; } @@ -9541,7 +10356,8 @@ declare var SVGNumberList: { new(): SVGNumberList; } -interface SVGPathElement extends SVGElement, SVGStylable, SVGTransformable, SVGTests, SVGLangSpace, SVGExternalResourcesRequired, SVGAnimatedPathData { +interface SVGPathElement extends SVGGraphicsElement { + readonly pathSegList: SVGPathSegList; createSVGPathSegArcAbs(x: number, y: number, r1: number, r2: number, angle: number, largeArcFlag: boolean, sweepFlag: boolean): SVGPathSegArcAbs; createSVGPathSegArcRel(x: number, y: number, r1: number, r2: number, angle: number, largeArcFlag: boolean, sweepFlag: boolean): SVGPathSegArcRel; createSVGPathSegClosePath(): SVGPathSegClosePath; @@ -9564,7 +10380,7 @@ interface SVGPathElement extends SVGElement, SVGStylable, SVGTransformable, SVGT getPathSegAtLength(distance: number): number; getPointAtLength(distance: number): SVGPoint; getTotalLength(): number; - addEventListener(type: K, listener: (this: SVGElement, ev: SVGElementEventMap[K]) => any, useCapture?: boolean): void; + addEventListener(type: K, listener: (this: SVGPathElement, ev: SVGElementEventMap[K]) => any, useCapture?: boolean): void; addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void; } @@ -9849,7 +10665,7 @@ declare var SVGPathSegMovetoRel: { new(): SVGPathSegMovetoRel; } -interface SVGPatternElement extends SVGElement, SVGStylable, SVGTests, SVGLangSpace, SVGExternalResourcesRequired, SVGFitToViewBox, SVGURIReference, SVGUnitTypes { +interface SVGPatternElement extends SVGElement, SVGTests, SVGUnitTypes, SVGFitToViewBox, SVGURIReference { readonly height: SVGAnimatedLength; readonly patternContentUnits: SVGAnimatedEnumeration; readonly patternTransform: SVGAnimatedTransformList; @@ -9857,7 +10673,7 @@ interface SVGPatternElement extends SVGElement, SVGStylable, SVGTests, SVGLangSp readonly width: SVGAnimatedLength; readonly x: SVGAnimatedLength; readonly y: SVGAnimatedLength; - addEventListener(type: K, listener: (this: SVGElement, ev: SVGElementEventMap[K]) => any, useCapture?: boolean): void; + addEventListener(type: K, listener: (this: SVGPatternElement, ev: SVGElementEventMap[K]) => any, useCapture?: boolean): void; addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void; } @@ -9893,8 +10709,8 @@ declare var SVGPointList: { new(): SVGPointList; } -interface SVGPolygonElement extends SVGElement, SVGStylable, SVGTransformable, SVGTests, SVGLangSpace, SVGExternalResourcesRequired, SVGAnimatedPoints { - addEventListener(type: K, listener: (this: SVGElement, ev: SVGElementEventMap[K]) => any, useCapture?: boolean): void; +interface SVGPolygonElement extends SVGGraphicsElement, SVGAnimatedPoints { + addEventListener(type: K, listener: (this: SVGPolygonElement, ev: SVGElementEventMap[K]) => any, useCapture?: boolean): void; addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void; } @@ -9903,8 +10719,8 @@ declare var SVGPolygonElement: { new(): SVGPolygonElement; } -interface SVGPolylineElement extends SVGElement, SVGStylable, SVGTransformable, SVGTests, SVGLangSpace, SVGExternalResourcesRequired, SVGAnimatedPoints { - addEventListener(type: K, listener: (this: SVGElement, ev: SVGElementEventMap[K]) => any, useCapture?: boolean): void; +interface SVGPolylineElement extends SVGGraphicsElement, SVGAnimatedPoints { + addEventListener(type: K, listener: (this: SVGPolylineElement, ev: SVGElementEventMap[K]) => any, useCapture?: boolean): void; addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void; } @@ -9957,6 +10773,8 @@ interface SVGRadialGradientElement extends SVGGradientElement { readonly fx: SVGAnimatedLength; readonly fy: SVGAnimatedLength; readonly r: SVGAnimatedLength; + addEventListener(type: K, listener: (this: SVGRadialGradientElement, ev: SVGElementEventMap[K]) => any, useCapture?: boolean): void; + addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void; } declare var SVGRadialGradientElement: { @@ -9976,14 +10794,14 @@ declare var SVGRect: { new(): SVGRect; } -interface SVGRectElement extends SVGElement, SVGStylable, SVGTransformable, SVGTests, SVGLangSpace, SVGExternalResourcesRequired { +interface SVGRectElement extends SVGGraphicsElement { readonly height: SVGAnimatedLength; readonly rx: SVGAnimatedLength; readonly ry: SVGAnimatedLength; readonly width: SVGAnimatedLength; readonly x: SVGAnimatedLength; readonly y: SVGAnimatedLength; - addEventListener(type: K, listener: (this: SVGElement, ev: SVGElementEventMap[K]) => any, useCapture?: boolean): void; + addEventListener(type: K, listener: (this: SVGRectElement, ev: SVGElementEventMap[K]) => any, useCapture?: boolean): void; addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void; } @@ -10001,7 +10819,7 @@ interface SVGSVGElementEventMap extends SVGElementEventMap { "SVGZoom": SVGZoomEvent; } -interface SVGSVGElement extends SVGElement, DocumentEvent, SVGLocatable, SVGTests, SVGStylable, SVGLangSpace, SVGExternalResourcesRequired, SVGFitToViewBox, SVGZoomAndPan { +interface SVGSVGElement extends SVGGraphicsElement, DocumentEvent, SVGFitToViewBox, SVGZoomAndPan { contentScriptType: string; contentStyleType: string; currentScale: number; @@ -10053,9 +10871,9 @@ declare var SVGSVGElement: { new(): SVGSVGElement; } -interface SVGScriptElement extends SVGElement, SVGExternalResourcesRequired, SVGURIReference { +interface SVGScriptElement extends SVGElement, SVGURIReference { type: string; - addEventListener(type: K, listener: (this: SVGElement, ev: SVGElementEventMap[K]) => any, useCapture?: boolean): void; + addEventListener(type: K, listener: (this: SVGScriptElement, ev: SVGElementEventMap[K]) => any, useCapture?: boolean): void; addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void; } @@ -10064,9 +10882,9 @@ declare var SVGScriptElement: { new(): SVGScriptElement; } -interface SVGStopElement extends SVGElement, SVGStylable { +interface SVGStopElement extends SVGElement { readonly offset: SVGAnimatedNumber; - addEventListener(type: K, listener: (this: SVGElement, ev: SVGElementEventMap[K]) => any, useCapture?: boolean): void; + addEventListener(type: K, listener: (this: SVGStopElement, ev: SVGElementEventMap[K]) => any, useCapture?: boolean): void; addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void; } @@ -10091,12 +10909,12 @@ declare var SVGStringList: { new(): SVGStringList; } -interface SVGStyleElement extends SVGElement, SVGLangSpace { +interface SVGStyleElement extends SVGElement { disabled: boolean; media: string; title: string; type: string; - addEventListener(type: K, listener: (this: SVGElement, ev: SVGElementEventMap[K]) => any, useCapture?: boolean): void; + addEventListener(type: K, listener: (this: SVGStyleElement, ev: SVGElementEventMap[K]) => any, useCapture?: boolean): void; addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void; } @@ -10105,8 +10923,8 @@ declare var SVGStyleElement: { new(): SVGStyleElement; } -interface SVGSwitchElement extends SVGElement, SVGStylable, SVGTransformable, SVGTests, SVGLangSpace, SVGExternalResourcesRequired { - addEventListener(type: K, listener: (this: SVGElement, ev: SVGElementEventMap[K]) => any, useCapture?: boolean): void; +interface SVGSwitchElement extends SVGGraphicsElement { + addEventListener(type: K, listener: (this: SVGSwitchElement, ev: SVGElementEventMap[K]) => any, useCapture?: boolean): void; addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void; } @@ -10115,8 +10933,8 @@ declare var SVGSwitchElement: { new(): SVGSwitchElement; } -interface SVGSymbolElement extends SVGElement, SVGStylable, SVGLangSpace, SVGExternalResourcesRequired, SVGFitToViewBox { - addEventListener(type: K, listener: (this: SVGElement, ev: SVGElementEventMap[K]) => any, useCapture?: boolean): void; +interface SVGSymbolElement extends SVGElement, SVGFitToViewBox { + addEventListener(type: K, listener: (this: SVGSymbolElement, ev: SVGElementEventMap[K]) => any, useCapture?: boolean): void; addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void; } @@ -10126,6 +10944,8 @@ declare var SVGSymbolElement: { } interface SVGTSpanElement extends SVGTextPositioningElement { + addEventListener(type: K, listener: (this: SVGTSpanElement, ev: SVGElementEventMap[K]) => any, useCapture?: boolean): void; + addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void; } declare var SVGTSpanElement: { @@ -10133,7 +10953,7 @@ declare var SVGTSpanElement: { new(): SVGTSpanElement; } -interface SVGTextContentElement extends SVGElement, SVGStylable, SVGTests, SVGLangSpace, SVGExternalResourcesRequired { +interface SVGTextContentElement extends SVGGraphicsElement { readonly lengthAdjust: SVGAnimatedEnumeration; readonly textLength: SVGAnimatedLength; getCharNumAtPosition(point: SVGPoint): number; @@ -10148,7 +10968,7 @@ interface SVGTextContentElement extends SVGElement, SVGStylable, SVGTests, SVGLa readonly LENGTHADJUST_SPACING: number; readonly LENGTHADJUST_SPACINGANDGLYPHS: number; readonly LENGTHADJUST_UNKNOWN: number; - addEventListener(type: K, listener: (this: SVGElement, ev: SVGElementEventMap[K]) => any, useCapture?: boolean): void; + addEventListener(type: K, listener: (this: SVGTextContentElement, ev: SVGElementEventMap[K]) => any, useCapture?: boolean): void; addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void; } @@ -10160,7 +10980,9 @@ declare var SVGTextContentElement: { readonly LENGTHADJUST_UNKNOWN: number; } -interface SVGTextElement extends SVGTextPositioningElement, SVGTransformable { +interface SVGTextElement extends SVGTextPositioningElement { + addEventListener(type: K, listener: (this: SVGTextElement, ev: SVGElementEventMap[K]) => any, useCapture?: boolean): void; + addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void; } declare var SVGTextElement: { @@ -10178,6 +11000,8 @@ interface SVGTextPathElement extends SVGTextContentElement, SVGURIReference { readonly TEXTPATH_SPACINGTYPE_AUTO: number; readonly TEXTPATH_SPACINGTYPE_EXACT: number; readonly TEXTPATH_SPACINGTYPE_UNKNOWN: number; + addEventListener(type: K, listener: (this: SVGTextPathElement, ev: SVGElementEventMap[K]) => any, useCapture?: boolean): void; + addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void; } declare var SVGTextPathElement: { @@ -10197,6 +11021,8 @@ interface SVGTextPositioningElement extends SVGTextContentElement { readonly rotate: SVGAnimatedNumberList; readonly x: SVGAnimatedLengthList; readonly y: SVGAnimatedLengthList; + addEventListener(type: K, listener: (this: SVGTextPositioningElement, ev: SVGElementEventMap[K]) => any, useCapture?: boolean): void; + addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void; } declare var SVGTextPositioningElement: { @@ -10204,8 +11030,8 @@ declare var SVGTextPositioningElement: { new(): SVGTextPositioningElement; } -interface SVGTitleElement extends SVGElement, SVGStylable, SVGLangSpace { - addEventListener(type: K, listener: (this: SVGElement, ev: SVGElementEventMap[K]) => any, useCapture?: boolean): void; +interface SVGTitleElement extends SVGElement { + addEventListener(type: K, listener: (this: SVGTitleElement, ev: SVGElementEventMap[K]) => any, useCapture?: boolean): void; addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void; } @@ -10270,14 +11096,14 @@ interface SVGUnitTypes { } declare var SVGUnitTypes: SVGUnitTypes; -interface SVGUseElement extends SVGElement, SVGStylable, SVGTransformable, SVGTests, SVGLangSpace, SVGExternalResourcesRequired, SVGURIReference { +interface SVGUseElement extends SVGGraphicsElement, SVGURIReference { readonly animatedInstanceRoot: SVGElementInstance; readonly height: SVGAnimatedLength; readonly instanceRoot: SVGElementInstance; readonly width: SVGAnimatedLength; readonly x: SVGAnimatedLength; readonly y: SVGAnimatedLength; - addEventListener(type: K, listener: (this: SVGElement, ev: SVGElementEventMap[K]) => any, useCapture?: boolean): void; + addEventListener(type: K, listener: (this: SVGUseElement, ev: SVGElementEventMap[K]) => any, useCapture?: boolean): void; addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void; } @@ -10286,9 +11112,9 @@ declare var SVGUseElement: { new(): SVGUseElement; } -interface SVGViewElement extends SVGElement, SVGExternalResourcesRequired, SVGFitToViewBox, SVGZoomAndPan { +interface SVGViewElement extends SVGElement, SVGZoomAndPan, SVGFitToViewBox { readonly viewTarget: SVGStringList; - addEventListener(type: K, listener: (this: SVGElement, ev: SVGElementEventMap[K]) => any, useCapture?: boolean): void; + addEventListener(type: K, listener: (this: SVGViewElement, ev: SVGElementEventMap[K]) => any, useCapture?: boolean): void; addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void; } @@ -10320,6 +11146,26 @@ declare var SVGZoomEvent: { new(): SVGZoomEvent; } +interface ScopedCredential { + readonly id: ArrayBuffer; + readonly type: string; +} + +declare var ScopedCredential: { + prototype: ScopedCredential; + new(): ScopedCredential; +} + +interface ScopedCredentialInfo { + readonly credential: ScopedCredential; + readonly publicKey: CryptoKey; +} + +declare var ScopedCredentialInfo: { + prototype: ScopedCredentialInfo; + new(): ScopedCredentialInfo; +} + interface ScreenEventMap { "MSOrientationChange": Event; } @@ -10381,6 +11227,10 @@ declare var ScriptProcessorNode: { interface Selection { readonly anchorNode: Node; readonly anchorOffset: number; + readonly baseNode: Node; + readonly baseOffset: number; + readonly extentNode: Node; + readonly extentOffset: number; readonly focusNode: Node; readonly focusOffset: number; readonly isCollapsed: boolean; @@ -10399,6 +11249,7 @@ interface Selection { removeRange(range: Range): void; selectAllChildren(parentNode: Node): void; setBaseAndExtent(baseNode: Node, baseOffset: number, extentNode: Node, extentOffset: number): void; + setPosition(parentNode: Node, offset: number): void; toString(): string; } @@ -10407,6 +11258,84 @@ declare var Selection: { new(): Selection; } +interface ServiceWorkerEventMap extends AbstractWorkerEventMap { + "statechange": Event; +} + +interface ServiceWorker extends EventTarget, AbstractWorker { + onstatechange: (this: ServiceWorker, ev: Event) => any; + readonly scriptURL: USVString; + readonly state: string; + postMessage(message: any, transfer?: any[]): void; + addEventListener(type: K, listener: (this: ServiceWorker, ev: ServiceWorkerEventMap[K]) => any, useCapture?: boolean): void; + addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void; +} + +declare var ServiceWorker: { + prototype: ServiceWorker; + new(): ServiceWorker; +} + +interface ServiceWorkerContainerEventMap { + "controllerchange": Event; + "message": ServiceWorkerMessageEvent; +} + +interface ServiceWorkerContainer extends EventTarget { + readonly controller: ServiceWorker | null; + oncontrollerchange: (this: ServiceWorkerContainer, ev: Event) => any; + onmessage: (this: ServiceWorkerContainer, ev: ServiceWorkerMessageEvent) => any; + readonly ready: PromiseLike; + getRegistration(clientURL?: USVString): PromiseLike; + getRegistrations(): any; + register(scriptURL: USVString, options?: RegistrationOptions): PromiseLike; + addEventListener(type: K, listener: (this: ServiceWorkerContainer, ev: ServiceWorkerContainerEventMap[K]) => any, useCapture?: boolean): void; + addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void; +} + +declare var ServiceWorkerContainer: { + prototype: ServiceWorkerContainer; + new(): ServiceWorkerContainer; +} + +interface ServiceWorkerMessageEvent extends Event { + readonly data: any; + readonly lastEventId: string; + readonly origin: string; + readonly ports: MessagePort[] | null; + readonly source: ServiceWorker | MessagePort | null; +} + +declare var ServiceWorkerMessageEvent: { + prototype: ServiceWorkerMessageEvent; + new(type: string, eventInitDict?: ServiceWorkerMessageEventInit): ServiceWorkerMessageEvent; +} + +interface ServiceWorkerRegistrationEventMap { + "updatefound": Event; +} + +interface ServiceWorkerRegistration extends EventTarget { + readonly active: ServiceWorker | null; + readonly installing: ServiceWorker | null; + onupdatefound: (this: ServiceWorkerRegistration, ev: Event) => any; + readonly pushManager: PushManager; + readonly scope: USVString; + readonly sync: SyncManager; + readonly waiting: ServiceWorker | null; + getNotifications(filter?: GetNotificationOptions): any; + showNotification(title: string, options?: NotificationOptions): PromiseLike; + unregister(): PromiseLike; + update(): PromiseLike; + addEventListener(type: K, listener: (this: ServiceWorkerRegistration, ev: ServiceWorkerRegistrationEventMap[K]) => any, useCapture?: boolean): void; + addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void; +} + +declare var ServiceWorkerRegistration: { + prototype: ServiceWorkerRegistration; + new(): ServiceWorkerRegistration; +} + interface SourceBuffer extends EventTarget { appendWindowEnd: number; appendWindowStart: number; @@ -10438,6 +11367,87 @@ declare var SourceBufferList: { new(): SourceBufferList; } +interface SpeechSynthesisEventMap { + "voiceschanged": Event; +} + +interface SpeechSynthesis extends EventTarget { + onvoiceschanged: (this: SpeechSynthesis, ev: Event) => any; + readonly paused: boolean; + readonly pending: boolean; + readonly speaking: boolean; + cancel(): void; + getVoices(): SpeechSynthesisVoice[]; + pause(): void; + resume(): void; + speak(utterance: SpeechSynthesisUtterance): void; + addEventListener(type: K, listener: (this: SpeechSynthesis, ev: SpeechSynthesisEventMap[K]) => any, useCapture?: boolean): void; + addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void; +} + +declare var SpeechSynthesis: { + prototype: SpeechSynthesis; + new(): SpeechSynthesis; +} + +interface SpeechSynthesisEvent extends Event { + readonly charIndex: number; + readonly elapsedTime: number; + readonly name: string; + readonly utterance: SpeechSynthesisUtterance | null; +} + +declare var SpeechSynthesisEvent: { + prototype: SpeechSynthesisEvent; + new(type: string, eventInitDict?: SpeechSynthesisEventInit): SpeechSynthesisEvent; +} + +interface SpeechSynthesisUtteranceEventMap { + "boundary": Event; + "end": Event; + "error": Event; + "mark": Event; + "pause": Event; + "resume": Event; + "start": Event; +} + +interface SpeechSynthesisUtterance extends EventTarget { + lang: string; + onboundary: (this: SpeechSynthesisUtterance, ev: Event) => any; + onend: (this: SpeechSynthesisUtterance, ev: Event) => any; + onerror: (this: SpeechSynthesisUtterance, ev: Event) => any; + onmark: (this: SpeechSynthesisUtterance, ev: Event) => any; + onpause: (this: SpeechSynthesisUtterance, ev: Event) => any; + onresume: (this: SpeechSynthesisUtterance, ev: Event) => any; + onstart: (this: SpeechSynthesisUtterance, ev: Event) => any; + pitch: number; + rate: number; + text: string; + voice: SpeechSynthesisVoice; + volume: number; + addEventListener(type: K, listener: (this: SpeechSynthesisUtterance, ev: SpeechSynthesisUtteranceEventMap[K]) => any, useCapture?: boolean): void; + addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void; +} + +declare var SpeechSynthesisUtterance: { + prototype: SpeechSynthesisUtterance; + new(text?: string): SpeechSynthesisUtterance; +} + +interface SpeechSynthesisVoice { + readonly default: boolean; + readonly lang: string; + readonly localService: boolean; + readonly name: string; + readonly voiceURI: string; +} + +declare var SpeechSynthesisVoice: { + prototype: SpeechSynthesisVoice; + new(): SpeechSynthesisVoice; +} + interface StereoPannerNode extends AudioNode { readonly pan: AudioParam; } @@ -10549,6 +11559,16 @@ declare var SubtleCrypto: { new(): SubtleCrypto; } +interface SyncManager { + getTags(): any; + register(tag: string): PromiseLike; +} + +declare var SyncManager: { + prototype: SyncManager; + new(): SyncManager; +} + interface Text extends CharacterData { readonly wholeText: string; readonly assignedSlot: HTMLSlotElement | null; @@ -10603,7 +11623,7 @@ declare var TextMetrics: { interface TextTrackEventMap { "cuechange": Event; - "error": ErrorEvent; + "error": Event; "load": Event; } @@ -10616,7 +11636,7 @@ interface TextTrack extends EventTarget { readonly language: string; mode: any; oncuechange: (this: TextTrack, ev: Event) => any; - onerror: (this: TextTrack, ev: ErrorEvent) => any; + onerror: (this: TextTrack, ev: Event) => any; onload: (this: TextTrack, ev: Event) => any; readonly readyState: number; addCue(cue: TextTrackCue): void; @@ -10728,11 +11748,14 @@ declare var Touch: { interface TouchEvent extends UIEvent { readonly altKey: boolean; readonly changedTouches: TouchList; + readonly charCode: number; readonly ctrlKey: boolean; + readonly keyCode: number; readonly metaKey: boolean; readonly shiftKey: boolean; readonly targetTouches: TouchList; readonly touches: TouchList; + readonly which: number; } declare var TouchEvent: { @@ -10752,12 +11775,12 @@ declare var TouchList: { } interface TrackEvent extends Event { - readonly track: any; + readonly track: VideoTrack | AudioTrack | TextTrack | null; } declare var TrackEvent: { prototype: TrackEvent; - new(): TrackEvent; + new(typeArg: string, eventInitDict?: TrackEventInit): TrackEvent; } interface TransitionEvent extends Event { @@ -10768,7 +11791,7 @@ interface TransitionEvent extends Event { declare var TransitionEvent: { prototype: TransitionEvent; - new(): TransitionEvent; + new(typeArg: string, eventInitDict?: TransitionEventInit): TransitionEvent; } interface TreeWalker { @@ -10799,7 +11822,7 @@ interface UIEvent extends Event { declare var UIEvent: { prototype: UIEvent; - new(type: string, eventInitDict?: UIEventInit): UIEvent; + new(typeArg: string, eventInitDict?: UIEventInit): UIEvent; } interface URL { @@ -10814,6 +11837,7 @@ interface URL { protocol: string; search: string; username: string; + readonly searchparams: URLSearchParams; toString(): string; } @@ -10950,6 +11974,28 @@ declare var WaveShaperNode: { new(): WaveShaperNode; } +interface WebAuthentication { + getAssertion(assertionChallenge: any, options?: AssertionOptions): PromiseLike; + makeCredential(accountInformation: Account, cryptoParameters: ScopedCredentialParameters[], attestationChallenge: any, options?: ScopedCredentialOptions): PromiseLike; +} + +declare var WebAuthentication: { + prototype: WebAuthentication; + new(): WebAuthentication; +} + +interface WebAuthnAssertion { + readonly authenticatorData: ArrayBuffer; + readonly clientData: ArrayBuffer; + readonly credential: ScopedCredential; + readonly signature: ArrayBuffer; +} + +declare var WebAuthnAssertion: { + prototype: WebAuthnAssertion; + new(): WebAuthnAssertion; +} + interface WebGLActiveInfo { readonly name: string; readonly size: number; @@ -10975,7 +12021,7 @@ interface WebGLContextEvent extends Event { declare var WebGLContextEvent: { prototype: WebGLContextEvent; - new(type: string, eventInitDict?: WebGLContextEventInit): WebGLContextEvent; + new(typeArg: string, eventInitDict?: WebGLContextEventInit): WebGLContextEvent; } interface WebGLFramebuffer extends WebGLObject { @@ -11102,7 +12148,7 @@ interface WebGLRenderingContext { isTexture(texture: WebGLTexture | null): boolean; lineWidth(width: number): void; linkProgram(program: WebGLProgram | null): void; - pixelStorei(pname: number, param: number): void; + pixelStorei(pname: number, param: number | boolean): void; polygonOffset(factor: number, units: number): void; readPixels(x: number, y: number, width: number, height: number, format: number, type: number, pixels: ArrayBufferView | null): void; renderbufferStorage(target: number, internalformat: number, width: number, height: number): void; @@ -11828,6 +12874,56 @@ declare var WebKitCSSMatrix: { new(text?: string): WebKitCSSMatrix; } +interface WebKitDirectoryEntry extends WebKitEntry { + createReader(): WebKitDirectoryReader; +} + +declare var WebKitDirectoryEntry: { + prototype: WebKitDirectoryEntry; + new(): WebKitDirectoryEntry; +} + +interface WebKitDirectoryReader { + readEntries(successCallback: WebKitEntriesCallback, errorCallback?: WebKitErrorCallback): void; +} + +declare var WebKitDirectoryReader: { + prototype: WebKitDirectoryReader; + new(): WebKitDirectoryReader; +} + +interface WebKitEntry { + readonly filesystem: WebKitFileSystem; + readonly fullPath: string; + readonly isDirectory: boolean; + readonly isFile: boolean; + readonly name: string; +} + +declare var WebKitEntry: { + prototype: WebKitEntry; + new(): WebKitEntry; +} + +interface WebKitFileEntry extends WebKitEntry { + file(successCallback: WebKitFileCallback, errorCallback?: WebKitErrorCallback): void; +} + +declare var WebKitFileEntry: { + prototype: WebKitFileEntry; + new(): WebKitFileEntry; +} + +interface WebKitFileSystem { + readonly name: string; + readonly root: WebKitDirectoryEntry; +} + +declare var WebKitFileSystem: { + prototype: WebKitFileSystem; + new(): WebKitFileSystem; +} + interface WebKitPoint { x: number; y: number; @@ -11840,7 +12936,7 @@ declare var WebKitPoint: { interface WebSocketEventMap { "close": CloseEvent; - "error": ErrorEvent; + "error": Event; "message": MessageEvent; "open": Event; } @@ -11850,7 +12946,7 @@ interface WebSocket extends EventTarget { readonly bufferedAmount: number; readonly extensions: string; onclose: (this: WebSocket, ev: CloseEvent) => any; - onerror: (this: WebSocket, ev: ErrorEvent) => any; + onerror: (this: WebSocket, ev: Event) => any; onmessage: (this: WebSocket, ev: MessageEvent) => any; onopen: (this: WebSocket, ev: Event) => any; readonly protocol: string; @@ -11987,8 +13083,9 @@ interface WindowEventMap extends GlobalEventHandlersEventMap { "waiting": Event; } -interface Window extends EventTarget, WindowTimers, WindowSessionStorage, WindowLocalStorage, WindowConsole, GlobalEventHandlers, IDBEnvironment, WindowBase64 { +interface Window extends EventTarget, WindowTimers, WindowSessionStorage, WindowLocalStorage, WindowConsole, GlobalEventHandlers, IDBEnvironment, WindowBase64, GlobalFetch { readonly applicationCache: ApplicationCache; + readonly caches: CacheStorage; readonly clientInformation: Navigator; readonly closed: boolean; readonly crypto: Crypto; @@ -12003,10 +13100,12 @@ interface Window extends EventTarget, WindowTimers, WindowSessionStorage, Window readonly history: History; readonly innerHeight: number; readonly innerWidth: number; + readonly isSecureContext: boolean; readonly length: number; readonly location: Location; readonly locationbar: BarProp; readonly menubar: BarProp; + readonly msContentScript: ExtensionScriptApis; readonly msCredentials: MSCredentials; name: string; readonly navigator: Navigator; @@ -12120,6 +13219,7 @@ interface Window extends EventTarget, WindowTimers, WindowSessionStorage, Window readonly scrollY: number; readonly scrollbars: BarProp; readonly self: Window; + readonly speechSynthesis: SpeechSynthesis; status: string; readonly statusbar: BarProp; readonly styleMedia: StyleMedia; @@ -12128,12 +13228,14 @@ interface Window extends EventTarget, WindowTimers, WindowSessionStorage, Window readonly window: Window; URL: typeof URL; Blob: typeof Blob; + customElements: CustomElementRegistry; alert(message?: any): void; blur(): void; cancelAnimationFrame(handle: number): void; captureEvents(): void; close(): void; confirm(message?: string): boolean; + departFocus(navigationReason: string, origin: FocusNavigationOrigin): void; focus(): void; getComputedStyle(elt: Element, pseudoElt?: string): CSSStyleDeclaration; getMatchedCSSRules(elt: Element, pseudoElt?: string): CSSRuleList; @@ -12153,6 +13255,7 @@ interface Window extends EventTarget, WindowTimers, WindowSessionStorage, Window scroll(x?: number, y?: number): void; scrollBy(x?: number, y?: number): void; scrollTo(x?: number, y?: number): void; + stop(): void; webkitCancelAnimationFrame(handle: number): void; webkitConvertPointFromNodeToPage(node: Node, pt: WebKitPoint): WebKitPoint; webkitConvertPointFromPageToNode(node: Node, pt: WebKitPoint): WebKitPoint; @@ -12175,7 +13278,7 @@ interface WorkerEventMap extends AbstractWorkerEventMap { interface Worker extends EventTarget, AbstractWorker { onmessage: (this: Worker, ev: MessageEvent) => any; - postMessage(message: any, ports?: any): void; + postMessage(message: any, transfer?: any[]): void; terminate(): void; addEventListener(type: K, listener: (this: Worker, ev: WorkerEventMap[K]) => any, useCapture?: boolean): void; addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void; @@ -12187,7 +13290,7 @@ declare var Worker: { } interface XMLDocument extends Document { - addEventListener(type: K, listener: (this: Document, ev: DocumentEventMap[K]) => any, useCapture?: boolean): void; + addEventListener(type: K, listener: (this: XMLDocument, ev: DocumentEventMap[K]) => any, useCapture?: boolean): void; addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void; } @@ -12206,14 +13309,14 @@ interface XMLHttpRequest extends EventTarget, XMLHttpRequestEventTarget { readonly response: any; readonly responseText: string; responseType: string; - readonly responseXML: any; + readonly responseURL: string; + readonly responseXML: Document | null; readonly status: number; readonly statusText: string; timeout: number; readonly upload: XMLHttpRequestUpload; withCredentials: boolean; msCaching?: string; - readonly responseURL: string; abort(): void; getAllResponseHeaders(): string; getResponseHeader(header: string): string | null; @@ -12241,11 +13344,10 @@ declare var XMLHttpRequest: { readonly LOADING: number; readonly OPENED: number; readonly UNSENT: number; - create(): XMLHttpRequest; } interface XMLHttpRequestUpload extends EventTarget, XMLHttpRequestEventTarget { - addEventListener(type: K, listener: (this: XMLHttpRequestEventTarget, ev: XMLHttpRequestEventTargetEventMap[K]) => any, useCapture?: boolean): void; + addEventListener(type: K, listener: (this: XMLHttpRequestUpload, ev: XMLHttpRequestEventTargetEventMap[K]) => any, useCapture?: boolean): void; addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void; } @@ -12345,6 +13447,16 @@ declare var XSLTProcessor: { new(): XSLTProcessor; } +interface webkitRTCPeerConnection extends RTCPeerConnection { + addEventListener(type: K, listener: (this: webkitRTCPeerConnection, ev: RTCPeerConnectionEventMap[K]) => any, useCapture?: boolean): void; + addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void; +} + +declare var webkitRTCPeerConnection: { + prototype: webkitRTCPeerConnection; + new(configuration: RTCConfiguration): webkitRTCPeerConnection; +} + interface AbstractWorkerEventMap { "error": ErrorEvent; } @@ -12355,6 +13467,14 @@ interface AbstractWorker { addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void; } +interface Body { + readonly bodyUsed: boolean; + arrayBuffer(): PromiseLike; + blob(): PromiseLike; + json(): PromiseLike; + text(): PromiseLike; +} + interface CanvasPathMethods { arc(x: number, y: number, radius: number, startAngle: number, endAngle: number, anticlockwise?: boolean): void; arcTo(x1: number, y1: number, x2: number, y2: number, radius: number): void; @@ -12381,12 +13501,10 @@ interface DOML2DeprecatedSizeProperty { interface DocumentEvent { createEvent(eventInterface:"AnimationEvent"): AnimationEvent; - createEvent(eventInterface:"AriaRequestEvent"): AriaRequestEvent; createEvent(eventInterface:"AudioProcessingEvent"): AudioProcessingEvent; createEvent(eventInterface:"BeforeUnloadEvent"): BeforeUnloadEvent; createEvent(eventInterface:"ClipboardEvent"): ClipboardEvent; createEvent(eventInterface:"CloseEvent"): CloseEvent; - createEvent(eventInterface:"CommandEvent"): CommandEvent; createEvent(eventInterface:"CompositionEvent"): CompositionEvent; createEvent(eventInterface:"CustomEvent"): CustomEvent; createEvent(eventInterface:"DeviceLightEvent"): DeviceLightEvent; @@ -12397,6 +13515,7 @@ interface DocumentEvent { createEvent(eventInterface:"Event"): Event; createEvent(eventInterface:"Events"): Event; createEvent(eventInterface:"FocusEvent"): FocusEvent; + createEvent(eventInterface:"FocusNavigationEvent"): FocusNavigationEvent; createEvent(eventInterface:"GamepadEvent"): GamepadEvent; createEvent(eventInterface:"HashChangeEvent"): HashChangeEvent; createEvent(eventInterface:"IDBVersionChangeEvent"): IDBVersionChangeEvent; @@ -12412,6 +13531,7 @@ interface DocumentEvent { createEvent(eventInterface:"MediaEncryptedEvent"): MediaEncryptedEvent; createEvent(eventInterface:"MediaKeyMessageEvent"): MediaKeyMessageEvent; createEvent(eventInterface:"MediaStreamErrorEvent"): MediaStreamErrorEvent; + createEvent(eventInterface:"MediaStreamEvent"): MediaStreamEvent; createEvent(eventInterface:"MediaStreamTrackEvent"): MediaStreamTrackEvent; createEvent(eventInterface:"MessageEvent"): MessageEvent; createEvent(eventInterface:"MouseEvent"): MouseEvent; @@ -12424,6 +13544,7 @@ interface DocumentEvent { createEvent(eventInterface:"OfflineAudioCompletionEvent"): OfflineAudioCompletionEvent; createEvent(eventInterface:"OverflowEvent"): OverflowEvent; createEvent(eventInterface:"PageTransitionEvent"): PageTransitionEvent; + createEvent(eventInterface:"PaymentRequestUpdateEvent"): PaymentRequestUpdateEvent; createEvent(eventInterface:"PermissionRequestedEvent"): PermissionRequestedEvent; createEvent(eventInterface:"PointerEvent"): PointerEvent; createEvent(eventInterface:"PopStateEvent"): PopStateEvent; @@ -12433,10 +13554,13 @@ interface DocumentEvent { createEvent(eventInterface:"RTCIceCandidatePairChangedEvent"): RTCIceCandidatePairChangedEvent; createEvent(eventInterface:"RTCIceGathererEvent"): RTCIceGathererEvent; createEvent(eventInterface:"RTCIceTransportStateChangedEvent"): RTCIceTransportStateChangedEvent; + createEvent(eventInterface:"RTCPeerConnectionIceEvent"): RTCPeerConnectionIceEvent; createEvent(eventInterface:"RTCSsrcConflictEvent"): RTCSsrcConflictEvent; createEvent(eventInterface:"SVGZoomEvent"): SVGZoomEvent; createEvent(eventInterface:"SVGZoomEvents"): SVGZoomEvent; createEvent(eventInterface:"ScriptNotifyEvent"): ScriptNotifyEvent; + createEvent(eventInterface:"ServiceWorkerMessageEvent"): ServiceWorkerMessageEvent; + createEvent(eventInterface:"SpeechSynthesisEvent"): SpeechSynthesisEvent; createEvent(eventInterface:"StorageEvent"): StorageEvent; createEvent(eventInterface:"TextEvent"): TextEvent; createEvent(eventInterface:"TouchEvent"): TouchEvent; @@ -12452,10 +13576,10 @@ interface DocumentEvent { interface ElementTraversal { readonly childElementCount: number; - readonly firstElementChild: Element; - readonly lastElementChild: Element; - readonly nextElementSibling: Element; - readonly previousElementSibling: Element; + readonly firstElementChild: Element | null; + readonly lastElementChild: Element | null; + readonly nextElementSibling: Element | null; + readonly previousElementSibling: Element | null; } interface GetSVGDocument { @@ -12488,6 +13612,10 @@ interface GlobalEventHandlers { addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void; } +interface GlobalFetch { + fetch(input: RequestInfo, init?: RequestInit): PromiseLike; +} + interface HTMLTableAlignment { /** * Sets or retrieves a value that you can use to implement your own ch functionality for the object. @@ -12551,6 +13679,14 @@ interface MSNavigatorDoNotTrack { storeWebWideTrackingException(args: StoreExceptionsInformation): void; } +interface NavigatorBeacon { + sendBeacon(url: USVString, data?: BodyInit): boolean; +} + +interface NavigatorConcurrentHardware { + readonly hardwareConcurrency: number; +} + interface NavigatorContentUtils { } @@ -12559,6 +13695,7 @@ interface NavigatorGeolocation { } interface NavigatorID { + readonly appCodeName: string; readonly appName: string; readonly appVersion: string; readonly platform: string; @@ -12592,20 +13729,12 @@ interface RandomSource { getRandomValues(array: ArrayBufferView): ArrayBufferView; } -interface SVGAnimatedPathData { - readonly pathSegList: SVGPathSegList; -} - interface SVGAnimatedPoints { readonly animatedPoints: SVGPointList; readonly points: SVGPointList; } -interface SVGExternalResourcesRequired { - readonly externalResourcesRequired: SVGAnimatedBoolean; -} - -interface SVGFilterPrimitiveStandardAttributes extends SVGStylable { +interface SVGFilterPrimitiveStandardAttributes { readonly height: SVGAnimatedLength; readonly result: SVGAnimatedString; readonly width: SVGAnimatedLength; @@ -12618,25 +13747,6 @@ interface SVGFitToViewBox { readonly viewBox: SVGAnimatedRect; } -interface SVGLangSpace { - xmllang: string; - xmlspace: string; -} - -interface SVGLocatable { - readonly farthestViewportElement: SVGElement; - readonly nearestViewportElement: SVGElement; - getBBox(): SVGRect; - getCTM(): SVGMatrix; - getScreenCTM(): SVGMatrix; - getTransformToElement(element: SVGElement): SVGMatrix; -} - -interface SVGStylable { - className: any; - readonly style: CSSStyleDeclaration; -} - interface SVGTests { readonly requiredExtensions: SVGStringList; readonly requiredFeatures: SVGStringList; @@ -12644,10 +13754,6 @@ interface SVGTests { hasExtension(extension: string): boolean; } -interface SVGTransformable extends SVGLocatable { - readonly transform: SVGAnimatedTransformList; -} - interface SVGURIReference { readonly href: SVGAnimatedString; } @@ -12706,6 +13812,14 @@ interface XMLHttpRequestEventTarget { addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void; } +interface ErrorEventInit { + message?: string; + filename?: string; + lineno?: number; + conlno?: number; + error?: any; +} + interface StorageEventInit extends EventInit { key?: string; oldValue?: string; @@ -12721,6 +13835,41 @@ interface Canvas2DContextAttributes { [attribute: string]: boolean | string | undefined; } +interface URLSearchParams { + /** + * Appends a specified key/value pair as a new search parameter. + */ + append(name: string, value: string): void; + /** + * Deletes the given search parameter, and its associated value, from the list of all search parameters. + */ + delete(name: string): void; + /** + * Returns the first value associated to the given search parameter. + */ + get(name: string): string | null; + /** + * Returns all the values association with a given search parameter. + */ + getAll(name: string): string[]; + /** + * Returns a Boolean indicating if such a search parameter exists. + */ + has(name: string): boolean; + /** + * Sets the value associated to a given search parameter to the given value. If there were several values, delete the others. + */ + set(name: string, value: string): void; +} + +declare var URLSearchParams: { + prototype: URLSearchParams; + /** + * Constructor returning a URLSearchParams object. + */ + new (init?: string | URLSearchParams): URLSearchParams; +} + interface NodeListOf extends NodeList { length: number; item(index: number): TNode; @@ -12730,7 +13879,6 @@ interface NodeListOf extends NodeList { interface HTMLCollectionOf extends HTMLCollection { item(index: number): T; namedItem(name: string): T; - [index: number]: T; } interface BlobPropertyBag { @@ -12747,15 +13895,6 @@ interface EventListenerObject { handleEvent(evt: Event): void; } -interface MessageEventInit extends EventInit { - data?: any; - origin?: string; - lastEventId?: string; - channel?: string; - source?: any; - ports?: MessagePort[]; -} - interface ProgressEventInit extends EventInit { lengthComputable?: boolean; loaded?: number; @@ -12957,8 +14096,8 @@ interface JsonWebKey { interface ParentNode { readonly children: HTMLCollection; - readonly firstElementChild: Element; - readonly lastElementChild: Element; + readonly firstElementChild: Element | null; + readonly lastElementChild: Element | null; readonly childElementCount: number; } @@ -12989,6 +14128,26 @@ interface AssignedNodesOptions { flatten?: boolean; } +interface ElementDefinitionOptions { + extends: string; +} + +interface CustomElementRegistry { + define(name: string, constructor: Function, options?: ElementDefinitionOptions): void; + get(name: string): any; + whenDefined(name: string): PromiseLike; +} + +interface PromiseRejectionEvent extends Event { + readonly promise: PromiseLike; + readonly reason: any; +} + +interface PromiseRejectionEventInit extends EventInit { + promise: PromiseLike; + reason?: any; +} + declare type EventListenerOrEventListenerObject = EventListener | EventListenerObject; interface ErrorEventHandler { @@ -13024,6 +14183,18 @@ interface DecodeSuccessCallback { interface DecodeErrorCallback { (error: DOMException): void; } +interface VoidFunction { + (): void; +} +interface RTCSessionDescriptionCallback { + (sdp: RTCSessionDescription): void; +} +interface RTCPeerConnectionErrorCallback { + (error: DOMError): void; +} +interface RTCStatsCallback { + (report: RTCStatsReport): void; +} interface FunctionStringCallback { (data: string): void; } @@ -13036,6 +14207,12 @@ interface NavigatorUserMediaErrorCallback { interface ForEachCallback { (keyId: any, status: string): void; } +interface NotificationPermissionCallback { + (permission: string): void; +} +interface IntersectionObserverCallback { + (entries: IntersectionObserverEntry[], observer: IntersectionObserver): void; +} interface HTMLElementTagNameMap { "a": HTMLAnchorElement; "applet": HTMLAppletElement; @@ -13051,6 +14228,7 @@ interface HTMLElementTagNameMap { "caption": HTMLTableCaptionElement; "col": HTMLTableColElement; "colgroup": HTMLTableColElement; + "data": HTMLDataElement; "datalist": HTMLDataListElement; "del": HTMLModElement; "dir": HTMLDirectoryElement; @@ -13091,6 +14269,7 @@ interface HTMLElementTagNameMap { "ol": HTMLOListElement; "optgroup": HTMLOptGroupElement; "option": HTMLOptionElement; + "output": HTMLOutputElement; "p": HTMLParagraphElement; "param": HTMLParamElement; "picture": HTMLPictureElement; @@ -13110,6 +14289,7 @@ interface HTMLElementTagNameMap { "tfoot": HTMLTableSectionElement; "th": HTMLTableHeaderCellElement; "thead": HTMLTableSectionElement; + "time": HTMLTimeElement; "title": HTMLTitleElement; "tr": HTMLTableRowElement; "track": HTMLTrackElement; @@ -13147,6 +14327,7 @@ interface ElementTagNameMap { "code": HTMLElement; "col": HTMLTableColElement; "colgroup": HTMLTableColElement; + "data": HTMLDataElement; "datalist": HTMLDataListElement; "dd": HTMLElement; "defs": SVGDefsElement; @@ -13240,6 +14421,7 @@ interface ElementTagNameMap { "ol": HTMLOListElement; "optgroup": HTMLOptGroupElement; "option": HTMLOptionElement; + "output": HTMLOutputElement; "p": HTMLParagraphElement; "param": HTMLParamElement; "path": SVGPathElement; @@ -13282,6 +14464,7 @@ interface ElementTagNameMap { "tfoot": HTMLTableSectionElement; "th": HTMLTableHeaderCellElement; "thead": HTMLTableSectionElement; + "time": HTMLTimeElement; "title": HTMLTitleElement; "tr": HTMLTableRowElement; "track": HTMLTrackElement; @@ -13326,6 +14509,7 @@ interface ElementListTagNameMap { "code": NodeListOf; "col": NodeListOf; "colgroup": NodeListOf; + "data": NodeListOf; "datalist": NodeListOf; "dd": NodeListOf; "defs": NodeListOf; @@ -13419,6 +14603,7 @@ interface ElementListTagNameMap { "ol": NodeListOf; "optgroup": NodeListOf; "option": NodeListOf; + "output": NodeListOf; "p": NodeListOf; "param": NodeListOf; "path": NodeListOf; @@ -13461,6 +14646,7 @@ interface ElementListTagNameMap { "tfoot": NodeListOf; "th": NodeListOf; "thead": NodeListOf; + "time": NodeListOf; "title": NodeListOf; "tr": NodeListOf; "track": NodeListOf; @@ -13481,6 +14667,7 @@ declare var Audio: {new(src?: string): HTMLAudioElement; }; declare var Image: {new(width?: number, height?: number): HTMLImageElement; }; declare var Option: {new(text?: string, value?: string, defaultSelected?: boolean, selected?: boolean): HTMLOptionElement; }; declare var applicationCache: ApplicationCache; +declare var caches: CacheStorage; declare var clientInformation: Navigator; declare var closed: boolean; declare var crypto: Crypto; @@ -13495,10 +14682,12 @@ declare var frames: Window; declare var history: History; declare var innerHeight: number; declare var innerWidth: number; +declare var isSecureContext: boolean; declare var length: number; declare var location: Location; declare var locationbar: BarProp; declare var menubar: BarProp; +declare var msContentScript: ExtensionScriptApis; declare var msCredentials: MSCredentials; declare const name: never; declare var navigator: Navigator; @@ -13612,18 +14801,21 @@ declare var scrollX: number; declare var scrollY: number; declare var scrollbars: BarProp; declare var self: Window; +declare var speechSynthesis: SpeechSynthesis; declare var status: string; declare var statusbar: BarProp; declare var styleMedia: StyleMedia; declare var toolbar: BarProp; declare var top: Window; declare var window: Window; +declare var customElements: CustomElementRegistry; declare function alert(message?: any): void; declare function blur(): void; declare function cancelAnimationFrame(handle: number): void; declare function captureEvents(): void; declare function close(): void; declare function confirm(message?: string): boolean; +declare function departFocus(navigationReason: string, origin: FocusNavigationOrigin): void; declare function focus(): void; declare function getComputedStyle(elt: Element, pseudoElt?: string): CSSStyleDeclaration; declare function getMatchedCSSRules(elt: Element, pseudoElt?: string): CSSRuleList; @@ -13643,6 +14835,7 @@ declare function resizeTo(x?: number, y?: number): void; declare function scroll(x?: number, y?: number): void; declare function scrollBy(x?: number, y?: number): void; declare function scrollTo(x?: number, y?: number): void; +declare function stop(): void; declare function webkitCancelAnimationFrame(handle: number): void; declare function webkitConvertPointFromNodeToPage(node: Node, pt: WebKitPoint): WebKitPoint; declare function webkitConvertPointFromPageToNode(node: Node, pt: WebKitPoint): WebKitPoint; @@ -13677,10 +14870,13 @@ declare var onwheel: (this: Window, ev: WheelEvent) => any; declare var indexedDB: IDBFactory; declare function atob(encodedString: string): string; declare function btoa(rawString: string): string; +declare function fetch(input: RequestInfo, init?: RequestInit): PromiseLike; declare function addEventListener(type: K, listener: (this: Window, ev: WindowEventMap[K]) => any, useCapture?: boolean): void; declare function addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void; type AAGUID = string; type AlgorithmIdentifier = string | Algorithm; +type BodyInit = any; +type ByteString = string; type ConstrainBoolean = boolean | ConstrainBooleanParameters; type ConstrainDOMString = string | string[] | ConstrainDOMStringParameters; type ConstrainDouble = number | ConstrainDoubleRange; @@ -13700,6 +14896,7 @@ type GLsizeiptr = number; type GLubyte = number; type GLuint = number; type GLushort = number; +type HeadersInit = any; type IDBKeyPath = string; type KeyFormat = string; type KeyType = string; @@ -13707,8 +14904,10 @@ type KeyUsage = string; type MSInboundPayload = MSVideoRecvPayload | MSAudioRecvPayload; type MSLocalClientEvent = MSLocalClientEventBase | MSAudioLocalClientEvent; type MSOutboundPayload = MSVideoSendPayload | MSAudioSendPayload; -type RTCIceGatherCandidate = RTCIceCandidate | RTCIceCandidateComplete; +type RTCIceGatherCandidate = RTCIceCandidateDictionary | RTCIceCandidateComplete; type RTCTransport = RTCDtlsTransport | RTCSrtpSdesTransport; +type RequestInfo = Request | string; +type USVString = string; type payloadtype = number; type ScrollBehavior = "auto" | "instant" | "smooth"; type ScrollLogicalPosition = "start" | "center" | "end" | "nearest"; diff --git a/src/lib/webworker.generated.d.ts b/src/lib/webworker.generated.d.ts index 089d0bdc5d5..e949526641b 100644 --- a/src/lib/webworker.generated.d.ts +++ b/src/lib/webworker.generated.d.ts @@ -7,12 +7,29 @@ interface Algorithm { name: string; } +interface CacheQueryOptions { + ignoreSearch?: boolean; + ignoreMethod?: boolean; + ignoreVary?: boolean; + cacheName?: string; +} + +interface CloseEventInit extends EventInit { + wasClean?: boolean; + code?: number; + reason?: string; +} + interface EventInit { scoped?: boolean; bubbles?: boolean; cancelable?: boolean; } +interface GetNotificationOptions { + tag?: string; +} + interface IDBIndexParameters { multiEntry?: boolean; unique?: boolean; @@ -27,10 +44,101 @@ interface KeyAlgorithm { name?: string; } +interface MessageEventInit extends EventInit { + lastEventId?: string; + channel?: string; + data?: any; + origin?: string; + source?: any; + ports?: MessagePort[]; +} + +interface NotificationOptions { + dir?: string; + lang?: string; + body?: string; + tag?: string; + icon?: string; +} + +interface PushSubscriptionOptionsInit { + userVisibleOnly?: boolean; + applicationServerKey?: any; +} + +interface RequestInit { + method?: string; + headers?: any; + body?: any; + referrer?: string; + referrerPolicy?: string; + mode?: string; + credentials?: string; + cache?: string; + redirect?: string; + integrity?: string; + keepalive?: boolean; + window?: any; +} + +interface ResponseInit { + status?: number; + statusText?: string; + headers?: any; +} + +interface ClientQueryOptions { + includeUncontrolled?: boolean; + type?: string; +} + +interface ExtendableEventInit extends EventInit { +} + +interface ExtendableMessageEventInit extends ExtendableEventInit { + data?: any; + origin?: string; + lastEventId?: string; + source?: Client | ServiceWorker | MessagePort; + ports?: MessagePort[]; +} + +interface FetchEventInit extends ExtendableEventInit { + request?: Request; + clientId?: string; + isReload?: boolean; +} + +interface NotificationEventInit extends ExtendableEventInit { + notification?: Notification; + action?: string; +} + +interface PushEventInit extends ExtendableEventInit { + data?: any; +} + +interface SyncEventInit extends ExtendableEventInit { + tag?: string; + lastChance?: boolean; +} + interface EventListener { (evt: Event): void; } +interface WebKitEntriesCallback { + (evt: Event): void; +} + +interface WebKitErrorCallback { + (evt: Event): void; +} + +interface WebKitFileCallback { + (evt: Event): void; +} + interface AudioBuffer { readonly duration: number; readonly length: number; @@ -59,6 +167,34 @@ declare var Blob: { new (blobParts?: any[], options?: BlobPropertyBag): Blob; } +interface Cache { + add(request: RequestInfo): PromiseLike; + addAll(requests: RequestInfo[]): PromiseLike; + delete(request: RequestInfo, options?: CacheQueryOptions): PromiseLike; + keys(request?: RequestInfo, options?: CacheQueryOptions): any; + match(request: RequestInfo, options?: CacheQueryOptions): PromiseLike; + matchAll(request?: RequestInfo, options?: CacheQueryOptions): any; + put(request: RequestInfo, response: Response): PromiseLike; +} + +declare var Cache: { + prototype: Cache; + new(): Cache; +} + +interface CacheStorage { + delete(cacheName: string): PromiseLike; + has(cacheName: string): PromiseLike; + keys(): any; + match(request: RequestInfo, options?: CacheQueryOptions): PromiseLike; + open(cacheName: string): PromiseLike; +} + +declare var CacheStorage: { + prototype: CacheStorage; + new(): CacheStorage; +} + interface CloseEvent extends Event { readonly code: number; readonly reason: string; @@ -68,14 +204,14 @@ interface CloseEvent extends Event { declare var CloseEvent: { prototype: CloseEvent; - new(): CloseEvent; + new(typeArg: string, eventInitDict?: CloseEventInit): CloseEvent; } interface Console { assert(test?: boolean, message?: string, ...optionalParams: any[]): void; clear(): void; count(countTitle?: string): void; - debug(message?: string, ...optionalParams: any[]): void; + debug(message?: any, ...optionalParams: any[]): void; dir(value?: any, ...optionalParams: any[]): void; dirxml(value: any): void; error(message?: any, ...optionalParams: any[]): void; @@ -227,7 +363,7 @@ interface ErrorEvent extends Event { declare var ErrorEvent: { prototype: ErrorEvent; - new(): ErrorEvent; + new(type: string, errorEventInitDict?: ErrorEventInit): ErrorEvent; } interface Event { @@ -256,7 +392,7 @@ interface Event { declare var Event: { prototype: Event; - new(type: string, eventInitDict?: EventInit): Event; + new(typeArg: string, eventInitDict?: EventInit): Event; readonly AT_TARGET: number; readonly BUBBLING_PHASE: number; readonly CAPTURING_PHASE: number; @@ -301,7 +437,7 @@ interface FileReader extends EventTarget, MSBaseReader { readAsBinaryString(blob: Blob): void; readAsDataURL(blob: Blob): void; readAsText(blob: Blob, encoding?: string): void; - addEventListener(type: K, listener: (this: MSBaseReader, ev: MSBaseReaderEventMap[K]) => any, useCapture?: boolean): void; + addEventListener(type: K, listener: (this: FileReader, ev: MSBaseReaderEventMap[K]) => any, useCapture?: boolean): void; addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void; } @@ -310,6 +446,20 @@ declare var FileReader: { new(): FileReader; } +interface Headers { + append(name: string, value: string): void; + delete(name: string): void; + forEach(callback: ForEachCallback): void; + get(name: string): string | null; + has(name: string): boolean; + set(name: string, value: string): void; +} + +declare var Headers: { + prototype: Headers; + new(init?: any): Headers; +} + interface IDBCursor { readonly direction: string; key: IDBKeyRange | IDBValidKey; @@ -345,14 +495,14 @@ declare var IDBCursorWithValue: { interface IDBDatabaseEventMap { "abort": Event; - "error": ErrorEvent; + "error": Event; } interface IDBDatabase extends EventTarget { readonly name: string; readonly objectStoreNames: DOMStringList; onabort: (this: IDBDatabase, ev: Event) => any; - onerror: (this: IDBDatabase, ev: ErrorEvent) => any; + onerror: (this: IDBDatabase, ev: Event) => any; version: number; onversionchange: (ev: IDBVersionChangeEvent) => any; close(): void; @@ -455,13 +605,13 @@ declare var IDBOpenDBRequest: { } interface IDBRequestEventMap { - "error": ErrorEvent; + "error": Event; "success": Event; } interface IDBRequest extends EventTarget { readonly error: DOMError; - onerror: (this: IDBRequest, ev: ErrorEvent) => any; + onerror: (this: IDBRequest, ev: Event) => any; onsuccess: (this: IDBRequest, ev: Event) => any; readonly readyState: string; readonly result: any; @@ -479,7 +629,7 @@ declare var IDBRequest: { interface IDBTransactionEventMap { "abort": Event; "complete": Event; - "error": ErrorEvent; + "error": Event; } interface IDBTransaction extends EventTarget { @@ -488,7 +638,7 @@ interface IDBTransaction extends EventTarget { readonly mode: string; onabort: (this: IDBTransaction, ev: Event) => any; oncomplete: (this: IDBTransaction, ev: Event) => any; - onerror: (this: IDBTransaction, ev: ErrorEvent) => any; + onerror: (this: IDBTransaction, ev: Event) => any; abort(): void; objectStore(name: string): IDBObjectStore; readonly READ_ONLY: string; @@ -528,105 +678,6 @@ declare var ImageData: { new(array: Uint8ClampedArray, width: number, height: number): ImageData; } -interface MSApp { - clearTemporaryWebDataAsync(): MSAppAsyncOperation; - createBlobFromRandomAccessStream(type: string, seeker: any): Blob; - createDataPackage(object: any): any; - createDataPackageFromSelection(): any; - createFileFromStorageFile(storageFile: any): File; - createStreamFromInputStream(type: string, inputStream: any): MSStream; - execAsyncAtPriority(asynchronousCallback: MSExecAtPriorityFunctionCallback, priority: string, ...args: any[]): void; - execAtPriority(synchronousCallback: MSExecAtPriorityFunctionCallback, priority: string, ...args: any[]): any; - getCurrentPriority(): string; - getHtmlPrintDocumentSourceAsync(htmlDoc: any): PromiseLike; - getViewId(view: any): any; - isTaskScheduledAtPriorityOrHigher(priority: string): boolean; - pageHandlesAllApplicationActivations(enabled: boolean): void; - suppressSubdownloadCredentialPrompts(suppress: boolean): void; - terminateApp(exceptionObject: any): void; - readonly CURRENT: string; - readonly HIGH: string; - readonly IDLE: string; - readonly NORMAL: string; -} -declare var MSApp: MSApp; - -interface MSAppAsyncOperationEventMap { - "complete": Event; - "error": ErrorEvent; -} - -interface MSAppAsyncOperation extends EventTarget { - readonly error: DOMError; - oncomplete: (this: MSAppAsyncOperation, ev: Event) => any; - onerror: (this: MSAppAsyncOperation, ev: ErrorEvent) => any; - readonly readyState: number; - readonly result: any; - start(): void; - readonly COMPLETED: number; - readonly ERROR: number; - readonly STARTED: number; - addEventListener(type: K, listener: (this: MSAppAsyncOperation, ev: MSAppAsyncOperationEventMap[K]) => any, useCapture?: boolean): void; - addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void; -} - -declare var MSAppAsyncOperation: { - prototype: MSAppAsyncOperation; - new(): MSAppAsyncOperation; - readonly COMPLETED: number; - readonly ERROR: number; - readonly STARTED: number; -} - -interface MSBlobBuilder { - append(data: any, endings?: string): void; - getBlob(contentType?: string): Blob; -} - -declare var MSBlobBuilder: { - prototype: MSBlobBuilder; - new(): MSBlobBuilder; -} - -interface MSStream { - readonly type: string; - msClose(): void; - msDetachStream(): any; -} - -declare var MSStream: { - prototype: MSStream; - new(): MSStream; -} - -interface MSStreamReader extends EventTarget, MSBaseReader { - readonly error: DOMError; - readAsArrayBuffer(stream: MSStream, size?: number): void; - readAsBinaryString(stream: MSStream, size?: number): void; - readAsBlob(stream: MSStream, size?: number): void; - readAsDataURL(stream: MSStream, size?: number): void; - readAsText(stream: MSStream, encoding?: string, size?: number): void; - addEventListener(type: K, listener: (this: MSBaseReader, ev: MSBaseReaderEventMap[K]) => any, useCapture?: boolean): void; - addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void; -} - -declare var MSStreamReader: { - prototype: MSStreamReader; - new(): MSStreamReader; -} - -interface MediaQueryList { - readonly matches: boolean; - readonly media: string; - addListener(listener: MediaQueryListListener): void; - removeListener(listener: MediaQueryListListener): void; -} - -declare var MediaQueryList: { - prototype: MediaQueryList; - new(): MediaQueryList; -} - interface MessageChannel { readonly port1: MessagePort; readonly port2: MessagePort; @@ -657,7 +708,7 @@ interface MessagePortEventMap { interface MessagePort extends EventTarget { onmessage: (this: MessagePort, ev: MessageEvent) => any; close(): void; - postMessage(message?: any, ports?: any): void; + postMessage(message?: any, transfer?: any[]): void; start(): void; addEventListener(type: K, listener: (this: MessagePort, ev: MessagePortEventMap[K]) => any, useCapture?: boolean): void; addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void; @@ -668,6 +719,109 @@ declare var MessagePort: { new(): MessagePort; } +interface NotificationEventMap { + "click": Event; + "close": Event; + "error": Event; + "show": Event; +} + +interface Notification extends EventTarget { + readonly body: string; + readonly dir: string; + readonly icon: string; + readonly lang: string; + onclick: (this: Notification, ev: Event) => any; + onclose: (this: Notification, ev: Event) => any; + onerror: (this: Notification, ev: Event) => any; + onshow: (this: Notification, ev: Event) => any; + readonly permission: string; + readonly tag: string; + readonly title: string; + close(): void; + addEventListener(type: K, listener: (this: Notification, ev: NotificationEventMap[K]) => any, useCapture?: boolean): void; + addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void; +} + +declare var Notification: { + prototype: Notification; + new(title: string, options?: NotificationOptions): Notification; + requestPermission(callback?: NotificationPermissionCallback): PromiseLike; +} + +interface Performance { + readonly navigation: PerformanceNavigation; + readonly timing: PerformanceTiming; + clearMarks(markName?: string): void; + clearMeasures(measureName?: string): void; + clearResourceTimings(): void; + getEntries(): any; + getEntriesByName(name: string, entryType?: string): any; + getEntriesByType(entryType: string): any; + getMarks(markName?: string): any; + getMeasures(measureName?: string): any; + mark(markName: string): void; + measure(measureName: string, startMarkName?: string, endMarkName?: string): void; + now(): number; + setResourceTimingBufferSize(maxSize: number): void; + toJSON(): any; +} + +declare var Performance: { + prototype: Performance; + new(): Performance; +} + +interface PerformanceNavigation { + readonly redirectCount: number; + readonly type: number; + toJSON(): any; + readonly TYPE_BACK_FORWARD: number; + readonly TYPE_NAVIGATE: number; + readonly TYPE_RELOAD: number; + readonly TYPE_RESERVED: number; +} + +declare var PerformanceNavigation: { + prototype: PerformanceNavigation; + new(): PerformanceNavigation; + readonly TYPE_BACK_FORWARD: number; + readonly TYPE_NAVIGATE: number; + readonly TYPE_RELOAD: number; + readonly TYPE_RESERVED: number; +} + +interface PerformanceTiming { + readonly connectEnd: number; + readonly connectStart: number; + readonly domComplete: number; + readonly domContentLoadedEventEnd: number; + readonly domContentLoadedEventStart: number; + readonly domInteractive: number; + readonly domLoading: number; + readonly domainLookupEnd: number; + readonly domainLookupStart: number; + readonly fetchStart: number; + readonly loadEventEnd: number; + readonly loadEventStart: number; + readonly msFirstPaint: number; + readonly navigationStart: number; + readonly redirectEnd: number; + readonly redirectStart: number; + readonly requestStart: number; + readonly responseEnd: number; + readonly responseStart: number; + readonly unloadEventEnd: number; + readonly unloadEventStart: number; + readonly secureConnectionStart: number; + toJSON(): any; +} + +declare var PerformanceTiming: { + prototype: PerformanceTiming; + new(): PerformanceTiming; +} + interface Position { readonly coords: Coordinates; readonly timestamp: number; @@ -707,9 +861,156 @@ declare var ProgressEvent: { new(type: string, eventInitDict?: ProgressEventInit): ProgressEvent; } +interface PushManager { + getSubscription(): PromiseLike; + permissionState(options?: PushSubscriptionOptionsInit): PromiseLike; + subscribe(options?: PushSubscriptionOptionsInit): PromiseLike; +} + +declare var PushManager: { + prototype: PushManager; + new(): PushManager; +} + +interface PushSubscription { + readonly endpoint: USVString; + readonly options: PushSubscriptionOptions; + getKey(name: string): ArrayBuffer | null; + toJSON(): any; + unsubscribe(): PromiseLike; +} + +declare var PushSubscription: { + prototype: PushSubscription; + new(): PushSubscription; +} + +interface PushSubscriptionOptions { + readonly applicationServerKey: ArrayBuffer | null; + readonly userVisibleOnly: boolean; +} + +declare var PushSubscriptionOptions: { + prototype: PushSubscriptionOptions; + new(): PushSubscriptionOptions; +} + +interface ReadableStream { + readonly locked: boolean; + cancel(): PromiseLike; + getReader(): ReadableStreamReader; +} + +declare var ReadableStream: { + prototype: ReadableStream; + new(): ReadableStream; +} + +interface ReadableStreamReader { + cancel(): PromiseLike; + read(): PromiseLike; + releaseLock(): void; +} + +declare var ReadableStreamReader: { + prototype: ReadableStreamReader; + new(): ReadableStreamReader; +} + +interface Request extends Object, Body { + readonly cache: string; + readonly credentials: string; + readonly destination: string; + readonly headers: Headers; + readonly integrity: string; + readonly keepalive: boolean; + readonly method: string; + readonly mode: string; + readonly redirect: string; + readonly referrer: string; + readonly referrerPolicy: string; + readonly type: string; + readonly url: string; + clone(): Request; +} + +declare var Request: { + prototype: Request; + new(input: Request | string, init?: RequestInit): Request; +} + +interface Response extends Object, Body { + readonly body: ReadableStream | null; + readonly headers: Headers; + readonly ok: boolean; + readonly status: number; + readonly statusText: string; + readonly type: string; + readonly url: string; + clone(): Response; +} + +declare var Response: { + prototype: Response; + new(body?: any, init?: ResponseInit): Response; +} + +interface ServiceWorkerEventMap extends AbstractWorkerEventMap { + "statechange": Event; +} + +interface ServiceWorker extends EventTarget, AbstractWorker { + onstatechange: (this: ServiceWorker, ev: Event) => any; + readonly scriptURL: USVString; + readonly state: string; + postMessage(message: any, transfer?: any[]): void; + addEventListener(type: K, listener: (this: ServiceWorker, ev: ServiceWorkerEventMap[K]) => any, useCapture?: boolean): void; + addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void; +} + +declare var ServiceWorker: { + prototype: ServiceWorker; + new(): ServiceWorker; +} + +interface ServiceWorkerRegistrationEventMap { + "updatefound": Event; +} + +interface ServiceWorkerRegistration extends EventTarget { + readonly active: ServiceWorker | null; + readonly installing: ServiceWorker | null; + onupdatefound: (this: ServiceWorkerRegistration, ev: Event) => any; + readonly pushManager: PushManager; + readonly scope: USVString; + readonly sync: SyncManager; + readonly waiting: ServiceWorker | null; + getNotifications(filter?: GetNotificationOptions): any; + showNotification(title: string, options?: NotificationOptions): PromiseLike; + unregister(): PromiseLike; + update(): PromiseLike; + addEventListener(type: K, listener: (this: ServiceWorkerRegistration, ev: ServiceWorkerRegistrationEventMap[K]) => any, useCapture?: boolean): void; + addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void; +} + +declare var ServiceWorkerRegistration: { + prototype: ServiceWorkerRegistration; + new(): ServiceWorkerRegistration; +} + +interface SyncManager { + getTags(): any; + register(tag: string): PromiseLike; +} + +declare var SyncManager: { + prototype: SyncManager; + new(): SyncManager; +} + interface WebSocketEventMap { "close": CloseEvent; - "error": ErrorEvent; + "error": Event; "message": MessageEvent; "open": Event; } @@ -719,7 +1020,7 @@ interface WebSocket extends EventTarget { readonly bufferedAmount: number; readonly extensions: string; onclose: (this: WebSocket, ev: CloseEvent) => any; - onerror: (this: WebSocket, ev: ErrorEvent) => any; + onerror: (this: WebSocket, ev: Event) => any; onmessage: (this: WebSocket, ev: MessageEvent) => any; onopen: (this: WebSocket, ev: Event) => any; readonly protocol: string; @@ -750,7 +1051,7 @@ interface WorkerEventMap extends AbstractWorkerEventMap { interface Worker extends EventTarget, AbstractWorker { onmessage: (this: Worker, ev: MessageEvent) => any; - postMessage(message: any, ports?: any): void; + postMessage(message: any, transfer?: any[]): void; terminate(): void; addEventListener(type: K, listener: (this: Worker, ev: WorkerEventMap[K]) => any, useCapture?: boolean): void; addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void; @@ -771,6 +1072,7 @@ interface XMLHttpRequest extends EventTarget, XMLHttpRequestEventTarget { readonly response: any; readonly responseText: string; responseType: string; + readonly responseURL: string; readonly responseXML: any; readonly status: number; readonly statusText: string; @@ -778,7 +1080,6 @@ interface XMLHttpRequest extends EventTarget, XMLHttpRequestEventTarget { readonly upload: XMLHttpRequestUpload; withCredentials: boolean; msCaching?: string; - readonly responseURL: string; abort(): void; getAllResponseHeaders(): string; getResponseHeader(header: string): string | null; @@ -805,11 +1106,10 @@ declare var XMLHttpRequest: { readonly LOADING: number; readonly OPENED: number; readonly UNSENT: number; - create(): XMLHttpRequest; } interface XMLHttpRequestUpload extends EventTarget, XMLHttpRequestEventTarget { - addEventListener(type: K, listener: (this: XMLHttpRequestEventTarget, ev: XMLHttpRequestEventTargetEventMap[K]) => any, useCapture?: boolean): void; + addEventListener(type: K, listener: (this: XMLHttpRequestUpload, ev: XMLHttpRequestEventTargetEventMap[K]) => any, useCapture?: boolean): void; addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void; } @@ -828,6 +1128,18 @@ interface AbstractWorker { addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void; } +interface Body { + readonly bodyUsed: boolean; + arrayBuffer(): PromiseLike; + blob(): PromiseLike; + json(): PromiseLike; + text(): PromiseLike; +} + +interface GlobalFetch { + fetch(input: RequestInfo, init?: RequestInit): PromiseLike; +} + interface MSBaseReaderEventMap { "abort": Event; "error": ErrorEvent; @@ -854,7 +1166,16 @@ interface MSBaseReader { addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void; } +interface NavigatorBeacon { + sendBeacon(url: USVString, data?: BodyInit): boolean; +} + +interface NavigatorConcurrentHardware { + readonly hardwareConcurrency: number; +} + interface NavigatorID { + readonly appCodeName: string; readonly appName: string; readonly appVersion: string; readonly platform: string; @@ -900,6 +1221,81 @@ interface XMLHttpRequestEventTarget { addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void; } +interface Client { + readonly frameType: string; + readonly id: string; + readonly url: USVString; + postMessage(message: any, transfer?: any[]): void; +} + +declare var Client: { + prototype: Client; + new(): Client; +} + +interface Clients { + claim(): PromiseLike; + get(id: string): PromiseLike; + matchAll(options?: ClientQueryOptions): any; + openWindow(url: USVString): PromiseLike; +} + +declare var Clients: { + prototype: Clients; + new(): Clients; +} + +interface DedicatedWorkerGlobalScopeEventMap extends WorkerGlobalScopeEventMap { + "message": MessageEvent; +} + +interface DedicatedWorkerGlobalScope extends WorkerGlobalScope { + onmessage: (this: DedicatedWorkerGlobalScope, ev: MessageEvent) => any; + close(): void; + postMessage(message: any, transfer?: any[]): void; + addEventListener(type: K, listener: (this: DedicatedWorkerGlobalScope, ev: DedicatedWorkerGlobalScopeEventMap[K]) => any, useCapture?: boolean): void; + addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void; +} + +declare var DedicatedWorkerGlobalScope: { + prototype: DedicatedWorkerGlobalScope; + new(): DedicatedWorkerGlobalScope; +} + +interface ExtendableEvent extends Event { + waitUntil(f: PromiseLike): void; +} + +declare var ExtendableEvent: { + prototype: ExtendableEvent; + new(type: string, eventInitDict?: ExtendableEventInit): ExtendableEvent; +} + +interface ExtendableMessageEvent extends ExtendableEvent { + readonly data: any; + readonly lastEventId: string; + readonly origin: string; + readonly ports: MessagePort[] | null; + readonly source: Client | ServiceWorker | MessagePort | null; +} + +declare var ExtendableMessageEvent: { + prototype: ExtendableMessageEvent; + new(type: string, eventInitDict?: ExtendableMessageEventInit): ExtendableMessageEvent; +} + +interface FetchEvent extends ExtendableEvent { + readonly clientId: string | null; + readonly isReload: boolean; + readonly request: Request; + respondWith(r: PromiseLike): void; +} + +declare var FetchEvent: { + prototype: FetchEvent; + new(type: string, eventInitDict: FetchEventInit): FetchEvent; +} + interface FileReaderSync { readAsArrayBuffer(blob: Blob): any; readAsBinaryString(blob: Blob): void; @@ -912,17 +1308,105 @@ declare var FileReaderSync: { new(): FileReaderSync; } -interface WorkerGlobalScopeEventMap extends DedicatedWorkerGlobalScopeEventMap { +interface NotificationEvent extends ExtendableEvent { + readonly action: string; + readonly notification: Notification; +} + +declare var NotificationEvent: { + prototype: NotificationEvent; + new(type: string, eventInitDict: NotificationEventInit): NotificationEvent; +} + +interface PushEvent extends ExtendableEvent { + readonly data: PushMessageData | null; +} + +declare var PushEvent: { + prototype: PushEvent; + new(type: string, eventInitDict?: PushEventInit): PushEvent; +} + +interface PushMessageData { + arrayBuffer(): ArrayBuffer; + blob(): Blob; + json(): JSON; + text(): USVString; +} + +declare var PushMessageData: { + prototype: PushMessageData; + new(): PushMessageData; +} + +interface ServiceWorkerGlobalScopeEventMap extends WorkerGlobalScopeEventMap { + "activate": ExtendableEvent; + "fetch": FetchEvent; + "install": ExtendableEvent; + "message": ExtendableMessageEvent; + "notificationclick": NotificationEvent; + "notificationclose": NotificationEvent; + "push": PushEvent; + "pushsubscriptionchange": ExtendableEvent; + "sync": SyncEvent; +} + +interface ServiceWorkerGlobalScope extends WorkerGlobalScope { + readonly clients: Clients; + onactivate: (this: ServiceWorkerGlobalScope, ev: ExtendableEvent) => any; + onfetch: (this: ServiceWorkerGlobalScope, ev: FetchEvent) => any; + oninstall: (this: ServiceWorkerGlobalScope, ev: ExtendableEvent) => any; + onmessage: (this: ServiceWorkerGlobalScope, ev: ExtendableMessageEvent) => any; + onnotificationclick: (this: ServiceWorkerGlobalScope, ev: NotificationEvent) => any; + onnotificationclose: (this: ServiceWorkerGlobalScope, ev: NotificationEvent) => any; + onpush: (this: ServiceWorkerGlobalScope, ev: PushEvent) => any; + onpushsubscriptionchange: (this: ServiceWorkerGlobalScope, ev: ExtendableEvent) => any; + onsync: (this: ServiceWorkerGlobalScope, ev: SyncEvent) => any; + readonly registration: ServiceWorkerRegistration; + skipWaiting(): PromiseLike; + addEventListener(type: K, listener: (this: ServiceWorkerGlobalScope, ev: ServiceWorkerGlobalScopeEventMap[K]) => any, useCapture?: boolean): void; + addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void; +} + +declare var ServiceWorkerGlobalScope: { + prototype: ServiceWorkerGlobalScope; + new(): ServiceWorkerGlobalScope; +} + +interface SyncEvent extends ExtendableEvent { + readonly lastChance: boolean; + readonly tag: string; +} + +declare var SyncEvent: { + prototype: SyncEvent; + new(type: string, init: SyncEventInit): SyncEvent; +} + +interface WindowClient extends Client { + readonly focused: boolean; + readonly visibilityState: string; + focus(): PromiseLike; + navigate(url: USVString): PromiseLike; +} + +declare var WindowClient: { + prototype: WindowClient; + new(): WindowClient; +} + +interface WorkerGlobalScopeEventMap { "error": ErrorEvent; } -interface WorkerGlobalScope extends EventTarget, WorkerUtils, DedicatedWorkerGlobalScope, WindowConsole { +interface WorkerGlobalScope extends EventTarget, WorkerUtils, WindowConsole, GlobalFetch { + readonly caches: CacheStorage; + readonly isSecureContext: boolean; readonly location: WorkerLocation; onerror: (this: WorkerGlobalScope, ev: ErrorEvent) => any; + readonly performance: Performance; readonly self: WorkerGlobalScope; - close(): void; msWriteProfilerMark(profilerMarkName: string): void; - toString(): string; addEventListener(type: K, listener: (this: WorkerGlobalScope, ev: WorkerGlobalScopeEventMap[K]) => any, useCapture?: boolean): void; addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void; } @@ -937,6 +1421,7 @@ interface WorkerLocation { readonly host: string; readonly hostname: string; readonly href: string; + readonly origin: string; readonly pathname: string; readonly port: string; readonly protocol: string; @@ -949,7 +1434,7 @@ declare var WorkerLocation: { new(): WorkerLocation; } -interface WorkerNavigator extends Object, NavigatorID, NavigatorOnLine { +interface WorkerNavigator extends Object, NavigatorID, NavigatorOnLine, NavigatorBeacon, NavigatorConcurrentHardware { readonly hardwareConcurrency: number; } @@ -958,17 +1443,6 @@ declare var WorkerNavigator: { new(): WorkerNavigator; } -interface DedicatedWorkerGlobalScopeEventMap { - "message": MessageEvent; -} - -interface DedicatedWorkerGlobalScope { - onmessage: (this: DedicatedWorkerGlobalScope, ev: MessageEvent) => any; - postMessage(data: any): void; - addEventListener(type: K, listener: (this: DedicatedWorkerGlobalScope, ev: DedicatedWorkerGlobalScopeEventMap[K]) => any, useCapture?: boolean): void; - addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void; -} - interface WorkerUtils extends Object, WindowBase64 { readonly indexedDB: IDBFactory; readonly msIndexedDB: IDBFactory; @@ -985,6 +1459,14 @@ interface WorkerUtils extends Object, WindowBase64 { setTimeout(handler: any, timeout?: any, ...args: any[]): number; } +interface ErrorEventInit { + message?: string; + filename?: string; + lineno?: number; + conlno?: number; + error?: any; +} + interface BlobPropertyBag { type?: string; endings?: string; @@ -999,15 +1481,6 @@ interface EventListenerObject { handleEvent(evt: Event): void; } -interface MessageEventInit extends EventInit { - data?: any; - origin?: string; - lastEventId?: string; - channel?: string; - source?: any; - ports?: MessagePort[]; -} - interface ProgressEventInit extends EventInit { lengthComputable?: boolean; loaded?: number; @@ -1199,18 +1672,6 @@ interface PositionCallback { interface PositionErrorCallback { (error: PositionError): void; } -interface MediaQueryListListener { - (mql: MediaQueryList): void; -} -interface MSLaunchUriCallback { - (): void; -} -interface MSUnsafeFunctionCallback { - (): any; -} -interface MSExecAtPriorityFunctionCallback { - (...args: any[]): any; -} interface DecodeSuccessCallback { (decodedData: AudioBuffer): void; } @@ -1220,12 +1681,22 @@ interface DecodeErrorCallback { interface FunctionStringCallback { (data: string): void; } -declare var location: WorkerLocation; -declare var onerror: (this: WorkerGlobalScope, ev: ErrorEvent) => any; -declare var self: WorkerGlobalScope; +interface ForEachCallback { + (keyId: any, status: string): void; +} +interface NotificationPermissionCallback { + (permission: string): void; +} +declare var onmessage: (this: DedicatedWorkerGlobalScope, ev: MessageEvent) => any; declare function close(): void; +declare function postMessage(message: any, transfer?: any[]): void; +declare var caches: CacheStorage; +declare var isSecureContext: boolean; +declare var location: WorkerLocation; +declare var onerror: (this: DedicatedWorkerGlobalScope, ev: ErrorEvent) => any; +declare var performance: Performance; +declare var self: WorkerGlobalScope; declare function msWriteProfilerMark(profilerMarkName: string): void; -declare function toString(): string; declare function dispatchEvent(evt: Event): boolean; declare function removeEventListener(type: string, listener?: EventListenerOrEventListenerObject, useCapture?: boolean): void; declare var indexedDB: IDBFactory; @@ -1243,12 +1714,16 @@ declare function setTimeout(handler: (...args: any[]) => void, timeout: number): declare function setTimeout(handler: any, timeout?: any, ...args: any[]): number; declare function atob(encodedString: string): string; declare function btoa(rawString: string): string; -declare var onmessage: (this: WorkerGlobalScope, ev: MessageEvent) => any; -declare function postMessage(data: any): void; declare var console: Console; -declare function addEventListener(type: K, listener: (this: WorkerGlobalScope, ev: WorkerGlobalScopeEventMap[K]) => any, useCapture?: boolean): void; +declare function fetch(input: RequestInfo, init?: RequestInit): PromiseLike; +declare function dispatchEvent(evt: Event): boolean; +declare function removeEventListener(type: string, listener?: EventListenerOrEventListenerObject, useCapture?: boolean): void; +declare function addEventListener(type: K, listener: (this: DedicatedWorkerGlobalScope, ev: DedicatedWorkerGlobalScopeEventMap[K]) => any, useCapture?: boolean): void; declare function addEventListener(type: string, listener: EventListenerOrEventListenerObject, useCapture?: boolean): void; type AlgorithmIdentifier = string | Algorithm; +type BodyInit = any; type IDBKeyPath = string; +type RequestInfo = Request | string; +type USVString = string; type IDBValidKey = number | string | Date | IDBArrayKey; type BufferSource = ArrayBuffer | ArrayBufferView; \ No newline at end of file diff --git a/tests/baselines/reference/modularizeLibrary_Dom.iterable.types b/tests/baselines/reference/modularizeLibrary_Dom.iterable.types index 054923fb5ee..b3758008918 100644 --- a/tests/baselines/reference/modularizeLibrary_Dom.iterable.types +++ b/tests/baselines/reference/modularizeLibrary_Dom.iterable.types @@ -3,9 +3,9 @@ for (const element of document.getElementsByTagName("a")) { >element : HTMLAnchorElement >document.getElementsByTagName("a") : NodeListOf ->document.getElementsByTagName : { (tagname: K): ElementListTagNameMap[K]; (tagname: string): NodeListOf; } +>document.getElementsByTagName : { (tagname: K): ElementListTagNameMap[K]; (tagname: string): NodeListOf; } >document : Document ->getElementsByTagName : { (tagname: K): ElementListTagNameMap[K]; (tagname: string): NodeListOf; } +>getElementsByTagName : { (tagname: K): ElementListTagNameMap[K]; (tagname: string): NodeListOf; } >"a" : "a" element.href; From 7a539d0b85bbf5da197660f0ad4246820c4dbe59 Mon Sep 17 00:00:00 2001 From: Ron Buckton Date: Fri, 3 Feb 2017 12:40:39 -0800 Subject: [PATCH 37/58] Identifier escaping/unescaping for unique names --- src/compiler/emitter.ts | 20 ++++++++++---------- src/compiler/factory.ts | 5 ++--- src/compiler/transformers/es2015.ts | 4 ++-- src/compiler/transformers/ts.ts | 2 +- 4 files changed, 15 insertions(+), 16 deletions(-) diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index 498f65ad366..700102a7069 100644 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -2565,7 +2565,7 @@ namespace ts { // Node names generate unique names based on their original node // and are cached based on that node's id. const node = getNodeForGeneratedName(name); - return generateNameCached(node, getTextOfNode); + return generateNameCached(node); } else { // Auto, Loop, and Unique names are cached based on their unique @@ -2575,9 +2575,9 @@ namespace ts { } } - function generateNameCached(node: Node, getTextOfNode: (node: Node, includeTrivia?: boolean) => string) { + function generateNameCached(node: Node) { const nodeId = getNodeId(node); - return nodeIdToGeneratedName[nodeId] || (nodeIdToGeneratedName[nodeId] = unescapeIdentifier(generateNameForNode(node, getTextOfNode))); + return nodeIdToGeneratedName[nodeId] || (nodeIdToGeneratedName[nodeId] = unescapeIdentifier(generateNameForNode(node))); } /** @@ -2659,7 +2659,7 @@ namespace ts { /** * Generates a unique name for a ModuleDeclaration or EnumDeclaration. */ - function generateNameForModuleOrEnum(node: ModuleDeclaration | EnumDeclaration, getTextOfNode: (node: Node, includeTrivia?: boolean) => string) { + function generateNameForModuleOrEnum(node: ModuleDeclaration | EnumDeclaration) { const name = getTextOfNode(node.name); // Use module/enum name itself if it is unique, otherwise make a unique variation return isUniqueLocalName(name, node) ? name : makeUniqueName(name); @@ -2689,9 +2689,9 @@ namespace ts { return makeUniqueName("class"); } - function generateNameForMethodOrAccessor(node: MethodDeclaration | AccessorDeclaration, getTextOfNode: (node: Node, includeTrivia?: boolean) => string) { + function generateNameForMethodOrAccessor(node: MethodDeclaration | AccessorDeclaration) { if (isIdentifier(node.name)) { - return generateNameCached(node.name, getTextOfNode); + return generateNameCached(node.name); } return makeTempVariableName(TempFlags.Auto); } @@ -2699,13 +2699,13 @@ namespace ts { /** * Generates a unique name from a node. */ - function generateNameForNode(node: Node, getTextOfNode: (node: Node, includeTrivia?: boolean) => string): string { + function generateNameForNode(node: Node): string { switch (node.kind) { case SyntaxKind.Identifier: return makeUniqueName(getTextOfNode(node)); case SyntaxKind.ModuleDeclaration: case SyntaxKind.EnumDeclaration: - return generateNameForModuleOrEnum(node, getTextOfNode); + return generateNameForModuleOrEnum(node); case SyntaxKind.ImportDeclaration: case SyntaxKind.ExportDeclaration: return generateNameForImportOrExportDeclaration(node); @@ -2718,7 +2718,7 @@ namespace ts { case SyntaxKind.MethodDeclaration: case SyntaxKind.GetAccessor: case SyntaxKind.SetAccessor: - return generateNameForMethodOrAccessor(node, getTextOfNode); + return generateNameForMethodOrAccessor(node); default: return makeTempVariableName(TempFlags.Auto); } @@ -2734,7 +2734,7 @@ namespace ts { case GeneratedIdentifierKind.Loop: return makeTempVariableName(TempFlags._i); case GeneratedIdentifierKind.Unique: - return makeUniqueName(name.text); + return makeUniqueName(unescapeIdentifier(name.text)); } Debug.fail("Unsupported GeneratedIdentifierKind."); diff --git a/src/compiler/factory.ts b/src/compiler/factory.ts index ec1e0dafb79..d5f3d920436 100644 --- a/src/compiler/factory.ts +++ b/src/compiler/factory.ts @@ -108,7 +108,7 @@ namespace ts { export function createIdentifier(text: string): Identifier { const node = createSynthesizedNode(SyntaxKind.Identifier); - node.text = text ? escapeIdentifier(text) : undefined; + node.text = escapeIdentifier(text); node.originalKeywordKind = text ? stringToToken(text) : SyntaxKind.Unknown; node.autoGenerateKind = GeneratedIdentifierKind.None; node.autoGenerateId = 0; @@ -140,8 +140,7 @@ namespace ts { /** Create a unique name based on the supplied text. */ export function createUniqueName(text: string): Identifier { - const name = createIdentifier(""); - name.text = text; + const name = createIdentifier(text); name.autoGenerateKind = GeneratedIdentifierKind.Unique; name.autoGenerateId = nextAutoGenerateId; nextAutoGenerateId++; diff --git a/src/compiler/transformers/es2015.ts b/src/compiler/transformers/es2015.ts index 6d0c9b3c5fa..e0fd435a90d 100644 --- a/src/compiler/transformers/es2015.ts +++ b/src/compiler/transformers/es2015.ts @@ -2251,7 +2251,7 @@ namespace ts { // we don't want to emit a temporary variable for the RHS, just use it directly. const counter = createLoopVariable(); const rhsReference = expression.kind === SyntaxKind.Identifier - ? createUniqueName((expression).text) + ? createUniqueName(unescapeIdentifier((expression).text)) : createTempVariable(/*recordTempVariable*/ undefined); const elementAccess = createElementAccess(rhsReference, counter); @@ -2872,7 +2872,7 @@ namespace ts { else { loopParameters.push(createParameter(/*decorators*/ undefined, /*modifiers*/ undefined, /*dotDotDotToken*/ undefined, name)); if (resolver.getNodeCheckFlags(decl) & NodeCheckFlags.NeedsLoopOutParameter) { - const outParamName = createUniqueName("out_" + name.text); + const outParamName = createUniqueName("out_" + unescapeIdentifier(name.text)); loopOutParameters.push({ originalName: name, outParamName }); } } diff --git a/src/compiler/transformers/ts.ts b/src/compiler/transformers/ts.ts index b18ab67381e..4ef3bd5c067 100644 --- a/src/compiler/transformers/ts.ts +++ b/src/compiler/transformers/ts.ts @@ -3119,7 +3119,7 @@ namespace ts { function getClassAliasIfNeeded(node: ClassDeclaration) { if (resolver.getNodeCheckFlags(node) & NodeCheckFlags.ClassWithConstructorReference) { enableSubstitutionForClassAliases(); - const classAlias = createUniqueName(node.name && !isGeneratedIdentifier(node.name) ? node.name.text : "default"); + const classAlias = createUniqueName(node.name && !isGeneratedIdentifier(node.name) ? unescapeIdentifier(node.name.text) : "default"); classAliases[getOriginalNodeId(node)] = classAlias; hoistVariableDeclaration(classAlias); return classAlias; From bd98bc97bdf637d5b0c0cf2b90cb9139e3802d81 Mon Sep 17 00:00:00 2001 From: Ron Buckton Date: Fri, 3 Feb 2017 14:12:50 -0800 Subject: [PATCH 38/58] Add factory functions for rest of NodeEdgeTraversal --- src/compiler/factory.ts | 175 +++++++++++++++++++++-- src/compiler/types.ts | 14 +- src/compiler/utilities.ts | 13 ++ src/compiler/visitor.ts | 285 +++++++++++++++++--------------------- 4 files changed, 315 insertions(+), 172 deletions(-) diff --git a/src/compiler/factory.ts b/src/compiler/factory.ts index d5f3d920436..4c7693dd846 100644 --- a/src/compiler/factory.ts +++ b/src/compiler/factory.ts @@ -187,6 +187,20 @@ namespace ts { // Names + export function createQualifiedName(left: EntityName, right: string | Identifier) { + const node = createSynthesizedNode(SyntaxKind.QualifiedName); + node.left = left; + node.right = asName(right); + return node; + } + + export function updateQualifiedName(node: QualifiedName, left: EntityName, right: Identifier) { + return node.left !== left + || node.right !== right + ? updateNode(createQualifiedName(left, right), node) + : node; + } + export function createComputedPropertyName(expression: Expression) { const node = createSynthesizedNode(SyntaxKind.ComputedPropertyName); node.expression = expression; @@ -502,6 +516,20 @@ namespace ts { : node; } + export function createTypeAssertion(type: TypeNode, expression: Expression) { + const node = createSynthesizedNode(SyntaxKind.TypeAssertionExpression); + node.type = type; + node.expression = parenthesizePrefixOperand(expression); + return node; + } + + export function updateTypeAssertion(node: TypeAssertion, type: TypeNode, expression: Expression) { + return node.type !== type + || node.expression !== expression + ? updateNode(createTypeAssertion(type, expression), node) + : node; + } + export function createParen(expression: Expression) { const node = createSynthesizedNode(SyntaxKind.ParenthesizedExpression); node.expression = expression; @@ -749,6 +777,32 @@ namespace ts { : node; } + export function createAsExpression(expression: Expression, type: TypeNode) { + const node = createSynthesizedNode(SyntaxKind.AsExpression); + node.expression = expression; + node.type = type; + return node; + } + + export function updateAsExpression(node: AsExpression, expression: Expression, type: TypeNode) { + return node.expression !== expression + || node.type !== type + ? updateNode(createAsExpression(expression, type), node) + : node; + } + + export function createNonNullExpression(expression: Expression) { + const node = createSynthesizedNode(SyntaxKind.NonNullExpression); + node.expression = parenthesizeForAccess(expression); + return node; + } + + export function updateNonNullExpression(node: NonNullExpression, expression: Expression) { + return node.expression !== expression + ? updateNode(createNonNullExpression(expression), node) + : node; + } + // Misc export function createTemplateSpan(expression: Expression, literal: TemplateMiddle | TemplateTail) { @@ -1040,18 +1094,6 @@ namespace ts { : node; } - export function createCaseBlock(clauses: CaseOrDefaultClause[]): CaseBlock { - const node = createSynthesizedNode(SyntaxKind.CaseBlock); - node.clauses = createNodeArray(clauses); - return node; - } - - export function updateCaseBlock(node: CaseBlock, clauses: CaseOrDefaultClause[]) { - return node.clauses !== clauses - ? updateNode(createCaseBlock(clauses), node) - : node; - } - export function createFunctionDeclaration(decorators: Decorator[], modifiers: Modifier[], asteriskToken: AsteriskToken, name: string | Identifier, typeParameters: TypeParameterDeclaration[], parameters: ParameterDeclaration[], type: TypeNode, body: Block) { const node = createSynthesizedNode(SyntaxKind.FunctionDeclaration); node.decorators = asNodeArray(decorators); @@ -1099,6 +1141,85 @@ namespace ts { : node; } + export function createEnumDeclaration(decorators: Decorator[], modifiers: Modifier[], name: string | Identifier, members: EnumMember[]) { + const node = createSynthesizedNode(SyntaxKind.EnumDeclaration); + node.decorators = asNodeArray(decorators); + node.modifiers = asNodeArray(modifiers); + node.name = asName(name); + node.members = createNodeArray(members); + return node; + } + + export function updateEnumDeclaration(node: EnumDeclaration, decorators: Decorator[], modifiers: Modifier[], name: Identifier, members: EnumMember[]) { + return node.decorators !== decorators + || node.modifiers !== modifiers + || node.name !== name + || node.members !== members + ? updateNode(createEnumDeclaration(decorators, modifiers, name, members), node) + : node; + } + + export function createModuleDeclaration(decorators: Decorator[], modifiers: Modifier[], name: ModuleName, body: ModuleBody, flags?: NodeFlags) { + const node = createSynthesizedNode(SyntaxKind.ModuleDeclaration); + node.flags |= flags; + node.decorators = asNodeArray(decorators); + node.modifiers = asNodeArray(modifiers); + node.name = name; + node.body = body; + return node; + } + + export function updateModuleDeclaration(node: ModuleDeclaration, decorators: Decorator[], modifiers: Modifier[], name: ModuleName, body: ModuleBody) { + return node.decorators !== decorators + || node.modifiers !== modifiers + || node.name !== name + || node.body !== body + ? updateNode(createModuleDeclaration(decorators, modifiers, name, body, node.flags), node) + : node; + } + + export function createModuleBlock(statements: Statement[]) { + const node = createSynthesizedNode(SyntaxKind.CaseBlock); + node.statements = createNodeArray(statements); + return node; + } + + export function updateModuleBlock(node: ModuleBlock, statements: Statement[]) { + return node.statements !== statements + ? updateNode(createModuleBlock(statements), node) + : node; + } + + export function createCaseBlock(clauses: CaseOrDefaultClause[]): CaseBlock { + const node = createSynthesizedNode(SyntaxKind.CaseBlock); + node.clauses = createNodeArray(clauses); + return node; + } + + export function updateCaseBlock(node: CaseBlock, clauses: CaseOrDefaultClause[]) { + return node.clauses !== clauses + ? updateNode(createCaseBlock(clauses), node) + : node; + } + + export function createImportEqualsDeclaration(decorators: Decorator[], modifiers: Modifier[], name: string | Identifier, moduleReference: ModuleReference) { + const node = createSynthesizedNode(SyntaxKind.ImportEqualsDeclaration); + node.decorators = asNodeArray(decorators); + node.modifiers = asNodeArray(modifiers); + node.name = asName(name); + node.moduleReference = moduleReference; + return node; + } + + export function updateImportEqualsDeclaration(node: ImportEqualsDeclaration, decorators: Decorator[], modifiers: Modifier[], name: Identifier, moduleReference: ModuleReference) { + return node.decorators !== decorators + || node.modifiers !== modifiers + || node.name !== name + || node.moduleReference !== moduleReference + ? updateNode(createImportEqualsDeclaration(decorators, modifiers, name, moduleReference), node) + : node; + } + export function createImportDeclaration(decorators: Decorator[], modifiers: Modifier[], importClause: ImportClause, moduleSpecifier?: Expression): ImportDeclaration { const node = createSynthesizedNode(SyntaxKind.ImportDeclaration); node.decorators = asNodeArray(decorators); @@ -1228,6 +1349,20 @@ namespace ts { : node; } + // Module references + + export function createExternalModuleReference(expression: Expression) { + const node = createSynthesizedNode(SyntaxKind.ExternalModuleReference); + node.expression = expression; + return node; + } + + export function updateExternalModuleReference(node: ExternalModuleReference, expression: Expression) { + return node.expression !== expression + ? updateNode(createExternalModuleReference(expression), node) + : node; + } + // JSX export function createJsxElement(openingElement: JsxOpeningElement, children: JsxChild[], closingElement: JsxClosingElement) { @@ -1426,6 +1561,22 @@ namespace ts { return node; } + // Enum + + export function createEnumMember(name: string | PropertyName, initializer?: Expression) { + const node = createSynthesizedNode(SyntaxKind.EnumMember); + node.name = asName(name); + node.initializer = initializer && parenthesizeExpressionForList(initializer); + return node; + } + + export function updateEnumMember(node: EnumMember, name: PropertyName, initializer: Expression | undefined) { + return node.name !== name + || node.initializer !== initializer + ? updateNode(createEnumMember(name, initializer), node) + : node; + } + // Top-level nodes export function updateSourceFileNode(node: SourceFile, statements: Statement[]) { diff --git a/src/compiler/types.ts b/src/compiler/types.ts index ae678f429f1..49e744682bc 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -1771,24 +1771,28 @@ members: NodeArray; } - export type ModuleBody = ModuleBlock | ModuleDeclaration; - export type ModuleName = Identifier | StringLiteral; + export type ModuleBody = NamespaceBody | JSDocNamespaceBody; + export interface ModuleDeclaration extends DeclarationStatement { kind: SyntaxKind.ModuleDeclaration; name: Identifier | StringLiteral; - body?: ModuleBlock | NamespaceDeclaration | JSDocNamespaceDeclaration | Identifier; + body?: ModuleBody | JSDocNamespaceDeclaration | Identifier; } + export type NamespaceBody = ModuleBlock | NamespaceDeclaration; + export interface NamespaceDeclaration extends ModuleDeclaration { name: Identifier; - body: ModuleBlock | NamespaceDeclaration; + body: NamespaceBody; } + export type JSDocNamespaceBody = Identifier | JSDocNamespaceDeclaration; + export interface JSDocNamespaceDeclaration extends ModuleDeclaration { name: Identifier; - body: JSDocNamespaceDeclaration | Identifier; + body: JSDocNamespaceBody; } export interface ModuleBlock extends Node, Statement { diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index 66efce4fef8..91cd6a89b8b 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -3887,6 +3887,19 @@ namespace ts { export function isModuleBody(node: Node): node is ModuleBody { const kind = node.kind; return kind === SyntaxKind.ModuleBlock + || kind === SyntaxKind.ModuleDeclaration + || kind === SyntaxKind.Identifier; + } + + export function isNamespaceBody(node: Node): node is NamespaceBody { + const kind = node.kind; + return kind === SyntaxKind.ModuleBlock + || kind === SyntaxKind.ModuleDeclaration; + } + + export function isJSDocNamespaceBody(node: Node): node is JSDocNamespaceBody { + const kind = node.kind; + return kind === SyntaxKind.Identifier || kind === SyntaxKind.ModuleDeclaration; } diff --git a/src/compiler/visitor.ts b/src/compiler/visitor.ts index b6e0adc1294..63c3726fc10 100644 --- a/src/compiler/visitor.ts +++ b/src/compiler/visitor.ts @@ -6,97 +6,6 @@ namespace ts { export type VisitResult = T | T[]; - /** - * Describes an edge of a Node, used when traversing a syntax tree. - */ - interface NodeEdge { - /** The property name for the edge. */ - name: string; - - /** Indicates that the result is optional. */ - optional?: boolean; - - /** A callback used to test whether a node is valid. */ - test?: (node: Node) => node is Node; - - /** A callback used to lift a NodeArrayNode into a valid node. */ - lift?: (nodes: NodeArray) => Node; - - /** A callback used to parenthesize a node to preserve the intended order of operations. */ - parenthesize?: (value: Node, parentNode: Node) => Node; - }; - - /** - * Describes the shape of a Node. - */ - type NodeTraversalPath = NodeEdge[]; - - /** - * This map contains information about the shape of each Node in "types.ts" pertaining to how - * each node should be traversed during a transformation. - * - * Each edge corresponds to a property in a Node subtype that should be traversed when visiting - * each child. The properties are assigned in the order in which traversal should occur. - * - * We only add entries for nodes that do not have a create/update pair defined in factory.ts - * - * NOTE: This needs to be kept up to date with changes to nodes in "types.ts". Currently, this - * map is not comprehensive. Only node edges relevant to tree transformation are - * currently defined. We may extend this to be more comprehensive, and eventually - * supplant the existing `forEachChild` implementation if performance is not - * significantly impacted. - */ - function getNodeEdgeTraversal(kind: SyntaxKind): NodeTraversalPath { - switch (kind) { - case SyntaxKind.QualifiedName: return [ - { name: "left", test: isEntityName }, - { name: "right", test: isIdentifier } - ]; - case SyntaxKind.Decorator: return [ - { name: "expression", test: isLeftHandSideExpression } - ]; - case SyntaxKind.TypeAssertionExpression: return [ - { name: "type", test: isTypeNode }, - { name: "expression", test: isUnaryExpression } - ]; - case SyntaxKind.AsExpression: return [ - { name: "expression", test: isExpression }, - { name: "type", test: isTypeNode } - ]; - case SyntaxKind.NonNullExpression: return [ - { name: "expression", test: isLeftHandSideExpression } - ]; - case SyntaxKind.EnumDeclaration: return [ - { name: "decorators", test: isDecorator }, - { name: "modifiers", test: isModifier }, - { name: "name", test: isIdentifier }, - { name: "members", test: isEnumMember } - ]; - case SyntaxKind.ModuleDeclaration: return [ - { name: "decorators", test: isDecorator }, - { name: "modifiers", test: isModifier }, - { name: "name", test: isModuleName }, - { name: "body", test: isModuleBody } - ]; - case SyntaxKind.ModuleBlock: return [ - { name: "statements", test: isStatement } - ]; - case SyntaxKind.ImportEqualsDeclaration: return [ - { name: "decorators", test: isDecorator }, - { name: "modifiers", test: isModifier }, - { name: "name", test: isIdentifier }, - { name: "moduleReference", test: isModuleReference } - ]; - case SyntaxKind.ExternalModuleReference: return [ - { name: "expression", test: isExpression, optional: true } - ]; - case SyntaxKind.EnumMember: return [ - { name: "name", test: isPropertyName }, - { name: "initializer", test: isExpression, optional: true, parenthesize: parenthesizeExpressionForList } - ]; - } - } - function reduceNode(node: Node, f: (memo: T, node: Node) => T, initial: T) { return node ? f(initial, node) : initial; } @@ -107,8 +16,7 @@ namespace ts { /** * Similar to `reduceLeft`, performs a reduction against each child of a node. - * NOTE: Unlike `forEachChild`, this does *not* visit every node. Only nodes added to the - * `nodeEdgeTraversalMap` above will be visited. + * NOTE: Unlike `forEachChild`, this does *not* visit every node. * * @param node The node containing the children to reduce. * @param initial The initial value to supply to the reduction. @@ -145,6 +53,11 @@ namespace ts { break; // Names + case SyntaxKind.QualifiedName: + result = reduceNode((node).left, cbNode, result); + result = reduceNode((node).right, cbNode, result); + break; + case SyntaxKind.ComputedPropertyName: result = reduceNode((node).expression, cbNode, result); break; @@ -252,6 +165,11 @@ namespace ts { result = reduceNode((node).template, cbNode, result); break; + case SyntaxKind.TypeAssertionExpression: + result = reduceNode((node).type, cbNode, result); + result = reduceNode((node).expression, cbNode, result); + break; + case SyntaxKind.FunctionExpression: result = reduceNodes((node).modifiers, cbNodes, result); result = reduceNode((node).name, cbNode, result); @@ -314,6 +232,15 @@ namespace ts { result = reduceNodes((node).typeArguments, cbNodes, result); break; + case SyntaxKind.AsExpression: + result = reduceNode((node).expression, cbNode, result); + result = reduceNode((node).type, cbNode, result); + break; + + case SyntaxKind.NonNullExpression: + result = reduceNode((node).expression, cbNode, result); + break; + // Misc case SyntaxKind.TemplateSpan: result = reduceNode((node).expression, cbNode, result); @@ -415,10 +342,35 @@ namespace ts { result = reduceNodes((node).members, cbNodes, result); break; + case SyntaxKind.EnumDeclaration: + result = reduceNodes((node).decorators, cbNodes, result); + result = reduceNodes((node).modifiers, cbNodes, result); + result = reduceNode((node).name, cbNode, result); + result = reduceNodes((node).members, cbNodes, result); + break; + + case SyntaxKind.ModuleDeclaration: + result = reduceNodes((node).decorators, cbNodes, result); + result = reduceNodes((node).modifiers, cbNodes, result); + result = reduceNode((node).name, cbNode, result); + result = reduceNode((node).body, cbNode, result); + break; + + case SyntaxKind.ModuleBlock: + result = reduceNodes((node).statements, cbNodes, result); + break; + case SyntaxKind.CaseBlock: result = reduceNodes((node).clauses, cbNodes, result); break; + case SyntaxKind.ImportEqualsDeclaration: + result = reduceNodes((node).decorators, cbNodes, result); + result = reduceNodes((node).modifiers, cbNodes, result); + result = reduceNode((node).name, cbNode, result); + result = reduceNode((node).moduleReference, cbNode, result); + break; + case SyntaxKind.ImportDeclaration: result = reduceNodes((node).decorators, cbNodes, result); result = reduceNodes((node).modifiers, cbNodes, result); @@ -459,6 +411,11 @@ namespace ts { result = reduceNode((node).moduleSpecifier, cbNode, result); break; + // Module references + case SyntaxKind.ExternalModuleReference: + result = reduceNode((node).expression, cbNode, result); + break; + // JSX case SyntaxKind.JsxElement: result = reduceNode((node).openingElement, cbNode, result); @@ -519,30 +476,25 @@ namespace ts { break; case SyntaxKind.SpreadAssignment: - result = reduceNode((node as SpreadAssignment).expression, cbNode, result); + result = reduceNode((node).expression, cbNode, result); break; + // Enum + case SyntaxKind.EnumMember: + result = reduceNode((node).name, cbNode, result); + result = reduceNode((node).initializer, cbNode, result); + // Top-level nodes case SyntaxKind.SourceFile: result = reduceNodes((node).statements, cbNodes, result); break; + // Transformation nodes case SyntaxKind.PartiallyEmittedExpression: result = reduceNode((node).expression, cbNode, result); break; default: - const edgeTraversalPath = getNodeEdgeTraversal(kind); - if (edgeTraversalPath) { - for (const edge of edgeTraversalPath) { - const value = (>node)[edge.name]; - if (value !== undefined) { - result = isArray(value) - ? reduceNodes(>value, cbNodes, result) - : cbNode(result, value); - } - } - } break; } @@ -556,11 +508,9 @@ namespace ts { * @param visitor The callback used to visit the Node. * @param test A callback to execute to verify the Node is valid. * @param optional An optional value indicating whether the Node is itself optional. - * @param lift An optional callback to execute to lift a NodeArrayNode into a valid Node. + * @param lift An optional callback to execute to lift a NodeArray into a valid Node. */ - export function visitNode(node: T, visitor: (node: Node) => VisitResult, test: (node: Node) => boolean, optional?: boolean, lift?: (node: NodeArray) => T): T; - export function visitNode(node: T, visitor: (node: Node) => VisitResult, test: (node: Node) => boolean, optional: boolean, lift: (node: NodeArray) => T, parenthesize: (node: Node, parentNode: Node) => Node, parentNode: Node): T; - export function visitNode(node: Node, visitor: (node: Node) => VisitResult, test: (node: Node) => boolean, optional?: boolean, lift?: (node: Node[]) => Node, parenthesize?: (node: Node, parentNode: Node) => Node, parentNode?: Node): Node { + export function visitNode(node: T, visitor: (node: Node) => VisitResult, test: (node: Node) => boolean, optional?: boolean, lift?: (node: NodeArray) => T): T { if (node === undefined || visitor === undefined) { return node; } @@ -586,13 +536,9 @@ namespace ts { visitedNode = visited; } - if (parenthesize !== undefined) { - visitedNode = parenthesize(visitedNode, parentNode); - } - Debug.assertNode(visitedNode, test); aggregateTransformFlags(visitedNode); - return visitedNode; + return visitedNode; } /** @@ -604,14 +550,12 @@ namespace ts { * @param start An optional value indicating the starting offset at which to start visiting. * @param count An optional value indicating the maximum number of nodes to visit. */ - export function visitNodes(nodes: NodeArray, visitor: (node: Node) => VisitResult, test: (node: Node) => boolean, start?: number, count?: number): NodeArray; - export function visitNodes(nodes: NodeArray, visitor: (node: Node) => VisitResult, test: (node: Node) => boolean, start: number, count: number, parenthesize: (node: Node, parentNode: Node) => Node, parentNode: Node): NodeArray; - export function visitNodes(nodes: NodeArray, visitor: (node: Node) => VisitResult, test: (node: Node) => boolean, start?: number, count?: number, parenthesize?: (node: Node, parentNode: Node) => Node, parentNode?: Node): NodeArray { + export function visitNodes(nodes: NodeArray, visitor: (node: Node) => VisitResult, test: (node: Node) => boolean, start?: number, count?: number): NodeArray { if (nodes === undefined) { return undefined; } - let updated: NodeArray; + let updated: NodeArray; // Ensure start and count have valid values const length = nodes.length; @@ -627,7 +571,7 @@ namespace ts { // If we are not visiting all of the original nodes, we must always create a new array. // Since this is a fragment of a node array, we do not copy over the previous location // and will only copy over `hasTrailingComma` if we are including the last element. - updated = createNodeArray([], /*hasTrailingComma*/ nodes.hasTrailingComma && start + count === length); + updated = createNodeArray([], /*hasTrailingComma*/ nodes.hasTrailingComma && start + count === length); } // Visit each original node. @@ -644,21 +588,15 @@ namespace ts { if (visited) { if (isArray(visited)) { for (let visitedNode of visited) { - visitedNode = parenthesize - ? parenthesize(visitedNode, parentNode) - : visitedNode; Debug.assertNode(visitedNode, test); aggregateTransformFlags(visitedNode); - updated.push(visitedNode); + updated.push(visitedNode); } } else { - const visitedNode = parenthesize - ? parenthesize(visited, parentNode) - : visited; - Debug.assertNode(visitedNode, test); - aggregateTransformFlags(visitedNode); - updated.push(visitedNode); + Debug.assertNode(visited, test); + aggregateTransformFlags(visited); + updated.push(visited); } } } @@ -747,6 +685,11 @@ namespace ts { return node; // Names + case SyntaxKind.QualifiedName: + return updateQualifiedName(node, + visitNode((node).left, visitor, isEntityName), + visitNode((node).right, visitor, isIdentifier)); + case SyntaxKind.ComputedPropertyName: return updateComputedPropertyName(node, visitNode((node).expression, visitor, isExpression)); @@ -761,6 +704,10 @@ namespace ts { visitNode((node).type, visitor, isTypeNode, /*optional*/ true), visitNode((node).initializer, visitor, isExpression, /*optional*/ true)); + case SyntaxKind.Decorator: + return updateDecorator(node, + visitNode((node).expression, visitor, isExpression)); + // Type member case SyntaxKind.PropertyDeclaration: return updateProperty(node, @@ -856,6 +803,11 @@ namespace ts { visitNode((node).tag, visitor, isExpression), visitNode((node).template, visitor, isTemplateLiteral)); + case SyntaxKind.TypeAssertionExpression: + return updateTypeAssertion(node, + visitNode((node).type, visitor, isTypeNode), + visitNode((node).expression, visitor, isExpression)); + case SyntaxKind.ParenthesizedExpression: return updateParen(node, visitNode((node).expression, visitor, isExpression)); @@ -938,6 +890,15 @@ namespace ts { visitNodes((node).typeArguments, visitor, isTypeNode), visitNode((node).expression, visitor, isExpression)); + case SyntaxKind.AsExpression: + return updateAsExpression(node, + visitNode((node).expression, visitor, isExpression), + visitNode((node).type, visitor, isTypeNode)); + + case SyntaxKind.NonNullExpression: + return updateNonNullExpression(node, + visitNode((node).expression, visitor, isExpression)); + // Misc case SyntaxKind.TemplateSpan: return updateTemplateSpan(node, @@ -1059,10 +1020,35 @@ namespace ts { visitNodes((node).heritageClauses, visitor, isHeritageClause), visitNodes((node).members, visitor, isClassElement)); + case SyntaxKind.EnumDeclaration: + return updateEnumDeclaration(node, + visitNodes((node).decorators, visitor, isDecorator), + visitNodes((node).modifiers, visitor, isModifier), + visitNode((node).name, visitor, isIdentifier), + visitNodes((node).members, visitor, isEnumMember)); + + case SyntaxKind.ModuleDeclaration: + return updateModuleDeclaration(node, + visitNodes((node).decorators, visitor, isDecorator), + visitNodes((node).modifiers, visitor, isModifier), + visitNode((node).name, visitor, isIdentifier), + visitNode((node).body, visitor, isModuleBody)); + + case SyntaxKind.ModuleBlock: + return updateModuleBlock(node, + visitNodes((node).statements, visitor, isStatement)); + case SyntaxKind.CaseBlock: return updateCaseBlock(node, visitNodes((node).clauses, visitor, isCaseOrDefaultClause)); + case SyntaxKind.ImportEqualsDeclaration: + return updateImportEqualsDeclaration(node, + visitNodes((node).decorators, visitor, isDecorator), + visitNodes((node).modifiers, visitor, isModifier), + visitNode((node).name, visitor, isIdentifier), + visitNode((node).moduleReference, visitor, isModuleReference)); + case SyntaxKind.ImportDeclaration: return updateImportDeclaration(node, visitNodes((node).decorators, visitor, isDecorator), @@ -1110,6 +1096,11 @@ namespace ts { visitNode((node).propertyName, visitor, isIdentifier, /*optional*/ true), visitNode((node).name, visitor, isIdentifier)); + // Module references + case SyntaxKind.ExternalModuleReference: + return updateExternalModuleReference(node, + visitNode((node).expression, visitor, isExpression)); + // JSX case SyntaxKind.JsxElement: return updateJsxElement(node, @@ -1175,10 +1166,16 @@ namespace ts { visitNode((node).objectAssignmentInitializer, visitor, isExpression)); case SyntaxKind.SpreadAssignment: - return updateSpreadAssignment(node as SpreadAssignment, - visitNode((node as SpreadAssignment).expression, visitor, isExpression)); + return updateSpreadAssignment(node, + visitNode((node).expression, visitor, isExpression)); - // Top-level nodes + // Enum + case SyntaxKind.EnumMember: + return updateEnumMember(node, + visitNode((node).name, visitor, isPropertyName), + visitNode((node).initializer, visitor, isExpression, /*optional*/ true)); + + // Top-level nodes case SyntaxKind.SourceFile: return updateSourceFileNode(node, visitLexicalEnvironment((node).statements, visitor, context)); @@ -1189,30 +1186,8 @@ namespace ts { visitNode((node).expression, visitor, isExpression)); default: - let updated: Node & MapLike; - const edgeTraversalPath = getNodeEdgeTraversal(kind); - if (edgeTraversalPath) { - for (const edge of edgeTraversalPath) { - const value = >(>node)[edge.name]; - if (value !== undefined) { - const visited = isArray(value) - ? visitNodes(value, visitor, edge.test, 0, value.length, edge.parenthesize, node) - : visitNode(value, visitor, edge.test, edge.optional, edge.lift, edge.parenthesize, node); - if (updated !== undefined || visited !== value) { - if (updated === undefined) { - updated = getMutableClone(node); - } - if (visited !== value) { - updated[edge.name] = visited; - } - } - } - } - } - return updated ? updateNode(updated, node) : node; + return node; } - - // return node; } /** From 9a65a6642315d014c8a132a068f80ceaf71b7ac7 Mon Sep 17 00:00:00 2001 From: Ron Buckton Date: Sat, 4 Feb 2017 22:46:38 -0800 Subject: [PATCH 39/58] Fix linter error --- src/compiler/visitor.ts | 2 +- src/services/transform.ts | 29 +++++++++++++++++++++++++++++ 2 files changed, 30 insertions(+), 1 deletion(-) create mode 100644 src/services/transform.ts diff --git a/src/compiler/visitor.ts b/src/compiler/visitor.ts index 63c3726fc10..fd2b0314dda 100644 --- a/src/compiler/visitor.ts +++ b/src/compiler/visitor.ts @@ -587,7 +587,7 @@ namespace ts { } if (visited) { if (isArray(visited)) { - for (let visitedNode of visited) { + for (const visitedNode of visited) { Debug.assertNode(visitedNode, test); aggregateTransformFlags(visitedNode); updated.push(visitedNode); diff --git a/src/services/transform.ts b/src/services/transform.ts new file mode 100644 index 00000000000..c9107eea853 --- /dev/null +++ b/src/services/transform.ts @@ -0,0 +1,29 @@ +/// +/// +namespace ts { + /** + * Transform one or more source files using the supplied transformers. + * @param source A `SourceFile` or an array of `SourceFiles`. + * @param transformers An array of `Transformer` callbacks used to process the transformation. + */ + export function transform(source: SourceFile | SourceFile[], transformers: Transformer[]) { + const diagnostics: Diagnostic[] = []; + const compilerOptions: CompilerOptions = {}; + const sourceFiles = isArray(source) ? source : [source]; + const fileMap = arrayToMap(sourceFiles, sourceFile => sourceFile.fileName); + const emitHost: EmitHost = { + getCompilerOptions: () => compilerOptions, + getCanonicalFileName: fileName => fileName, + getCommonSourceDirectory: () => "", + getCurrentDirectory: () => "", + getNewLine: () => "\n", + getSourceFile: fileName => fileMap.get(fileName), + getSourceFileByPath: fileName => fileMap.get(fileName), + getSourceFiles: () => sourceFiles, + isSourceFileFromExternalLibrary: () => false, + isEmitBlocked: () => false, + writeFile: () => Debug.fail("'writeFile()' is not supported during transformation.") + }; + return transformFiles(/*resolver*/ undefined, emitHost, sourceFiles, transformers); + } +} \ No newline at end of file From eedc2619dbf343dd9e269eb75afb026e6464f449 Mon Sep 17 00:00:00 2001 From: Ron Buckton Date: Mon, 6 Feb 2017 15:28:54 -0800 Subject: [PATCH 40/58] Minor PR feedback --- src/compiler/factory.ts | 23 ----------------------- 1 file changed, 23 deletions(-) diff --git a/src/compiler/factory.ts b/src/compiler/factory.ts index 4c7693dd846..d5d8482a0ba 100644 --- a/src/compiler/factory.ts +++ b/src/compiler/factory.ts @@ -1766,8 +1766,6 @@ namespace ts { // Utilities - function asName(name: string): Identifier; - function asName(name: Identifier): Identifier; function asName(name: string | Identifier): Identifier; function asName(name: string | BindingName): BindingName; function asName(name: string | PropertyName): PropertyName; @@ -1811,8 +1809,6 @@ namespace ts { /** * Associates a node with the current transformation, initializing * various transient transformation properties. - * - * @param node The node. */ /* @internal */ export function getOrCreateEmitNode(node: Node) { @@ -1845,8 +1841,6 @@ namespace ts { /** * Gets flags that control emit behavior of a node. - * - * @param node The node. */ export function getEmitFlags(node: Node) { const emitNode = node.emitNode; @@ -1855,9 +1849,6 @@ namespace ts { /** * Sets flags that control emit behavior of a node. - * - * @param node The node. - * @param emitFlags The NodeEmitFlags for the node. */ export function setEmitFlags(node: T, emitFlags: EmitFlags) { getOrCreateEmitNode(node).flags = emitFlags; @@ -1866,8 +1857,6 @@ namespace ts { /** * Gets a custom text range to use when emitting source maps. - * - * @param node The node. */ export function getSourceMapRange(node: Node) { const emitNode = node.emitNode; @@ -1876,9 +1865,6 @@ namespace ts { /** * Sets a custom text range to use when emitting source maps. - * - * @param node The node. - * @param range The text range. */ export function setSourceMapRange(node: T, range: TextRange) { getOrCreateEmitNode(node).sourceMapRange = range; @@ -1887,9 +1873,6 @@ namespace ts { /** * Gets the TextRange to use for source maps for a token of a node. - * - * @param node The node. - * @param token The token. */ export function getTokenSourceMapRange(node: Node, token: SyntaxKind) { const emitNode = node.emitNode; @@ -1899,10 +1882,6 @@ namespace ts { /** * Sets the TextRange to use for source maps for a token of a node. - * - * @param node The node. - * @param token The token. - * @param range The text range. */ export function setTokenSourceMapRange(node: T, token: SyntaxKind, range: TextRange) { const emitNode = getOrCreateEmitNode(node); @@ -1913,8 +1892,6 @@ namespace ts { /** * Gets a custom text range to use when emitting comments. - * - * @param node The node. */ export function getCommentRange(node: Node) { const emitNode = node.emitNode; From c28edc31c05319157d3371a92a9bf3ced6543b87 Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Mon, 6 Feb 2017 15:53:00 -0800 Subject: [PATCH 41/58] Error on forward references for property initializers The error only appears when a property initializer references another property before its definition. References to outer variables, etc are still allowed. --- src/compiler/checker.ts | 41 +++++++++++++++++++++++++++++------------ 1 file changed, 29 insertions(+), 12 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index b5306771dd7..4423b574e31 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -641,7 +641,7 @@ namespace ts { } // declaration is after usage // can be legal if usage is deferred (i.e. inside function or in initializer of instance property) - if (isUsedInFunctionOrNonStaticProperty(usage)) { + if (isUsedInFunctionOrInstanceProperty(usage)) { return true; } const sourceFiles = host.getSourceFiles(); @@ -668,10 +668,12 @@ namespace ts { } - // declaration is after usage - // can be legal if usage is deferred (i.e. inside function or in initializer of instance property) + // declaration is after usage, but it can still be legal if usage is deferred: + // 1. inside a function + // 2. inside an instance property initializer, a reference to a non-instance property const container = getEnclosingBlockScopeContainer(declaration); - return isUsedInFunctionOrNonStaticProperty(usage, container); + const isInstanceProperty = declaration.kind === SyntaxKind.PropertyDeclaration && !(getModifierFlags(declaration) & ModifierFlags.Static); + return isUsedInFunctionOrInstanceProperty(usage, isInstanceProperty, container); function isImmediatelyUsedInInitializerOfBlockScopedVariable(declaration: VariableDeclaration, usage: Node): boolean { const container = getEnclosingBlockScopeContainer(declaration); @@ -700,7 +702,7 @@ namespace ts { return false; } - function isUsedInFunctionOrNonStaticProperty(usage: Node, container?: Node): boolean { + function isUsedInFunctionOrInstanceProperty(usage: Node, isDeclarationInstanceProperty?: boolean, container?: Node): boolean { let current = usage; while (current) { if (current === container) { @@ -711,13 +713,13 @@ namespace ts { return true; } - const initializerOfNonStaticProperty = current.parent && + const initializerOfInstanceProperty = current.parent && current.parent.kind === SyntaxKind.PropertyDeclaration && (getModifierFlags(current.parent) & ModifierFlags.Static) === 0 && (current.parent).initializer === current; - if (initializerOfNonStaticProperty) { - return true; + if (initializerOfInstanceProperty) { + return !isDeclarationInstanceProperty; } current = current.parent; @@ -986,10 +988,10 @@ namespace ts { // interface bar {} // } // const foo/*1*/: foo/*2*/.bar; - // The foo at /*1*/ and /*2*/ will share same symbol with two meaning - // block - scope variable and namespace module. However, only when we + // The foo at /*1*/ and /*2*/ will share same symbol with two meanings: + // block-scoped variable and namespace module. However, only when we // try to resolve name in /*1*/ which is used in variable position, - // we want to check for block- scoped + // we want to check for block-scoped if (meaning & SymbolFlags.BlockScopedVariable) { const exportOrLocalSymbol = getExportSymbolOfValueSymbolIfExported(result); if (exportOrLocalSymbol.flags & SymbolFlags.BlockScopedVariable) { @@ -1013,7 +1015,7 @@ namespace ts { return false; } - const container = getThisContainer(errorLocation, /* includeArrowFunctions */ true); + const container = getThisContainer(errorLocation, /*includeArrowFunctions*/ true); let location = container; while (location) { if (isClassLike(location.parent)) { @@ -12543,6 +12545,16 @@ namespace ts { } } + function isInPropertyInitializer(node: Node): boolean { + while (node) { + if (node.parent && node.parent.kind === SyntaxKind.PropertyDeclaration && (node.parent as PropertyDeclaration).initializer === node) { + return true; + } + node = node.parent; + } + return false; + } + function checkPropertyAccessExpressionOrQualifiedName(node: PropertyAccessExpression | QualifiedName, left: Expression | QualifiedName, right: Identifier) { const type = checkNonNullExpression(left); if (isTypeAny(type) || type === silentNeverType) { @@ -12565,6 +12577,11 @@ namespace ts { } return unknownType; } + if (prop.valueDeclaration && + isInPropertyInitializer(node) && + !isBlockScopedNameDeclaredBeforeUse(prop.valueDeclaration, right)) { + error(right, Diagnostics.Block_scoped_variable_0_used_before_its_declaration, right.text); + } markPropertyAsReferenced(prop); From 669ecab631aa50939e531a3c6df0706125e813fd Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Mon, 6 Feb 2017 16:05:40 -0800 Subject: [PATCH 42/58] Test property initialiser forward reference errors --- .../forwardRefInClassProperties.errors.txt | 27 ++++++++++++++++ .../reference/forwardRefInClassProperties.js | 31 +++++++++++++++++++ .../compiler/forwardRefInClassProperties.ts | 14 +++++++++ 3 files changed, 72 insertions(+) create mode 100644 tests/baselines/reference/forwardRefInClassProperties.errors.txt create mode 100644 tests/baselines/reference/forwardRefInClassProperties.js create mode 100644 tests/cases/compiler/forwardRefInClassProperties.ts diff --git a/tests/baselines/reference/forwardRefInClassProperties.errors.txt b/tests/baselines/reference/forwardRefInClassProperties.errors.txt new file mode 100644 index 00000000000..dcf153076ed --- /dev/null +++ b/tests/baselines/reference/forwardRefInClassProperties.errors.txt @@ -0,0 +1,27 @@ +tests/cases/compiler/forwardRefInClassProperties.ts(3,15): error TS2448: Block-scoped variable '_a' used before its declaration. +tests/cases/compiler/forwardRefInClassProperties.ts(6,22): error TS2448: Block-scoped variable '_A' used before its declaration. +tests/cases/compiler/forwardRefInClassProperties.ts(11,17): error TS2448: Block-scoped variable 'b' used before its declaration. + + +==== tests/cases/compiler/forwardRefInClassProperties.ts (3 errors) ==== + class Test + { + _b = this._a; // undefined, no error/warning + ~~ +!!! error TS2448: Block-scoped variable '_a' used before its declaration. + _a = 3; + + static _B = Test._A; // undefined, no error/warning + ~~ +!!! error TS2448: Block-scoped variable '_A' used before its declaration. + static _A = 3; + + method() + { + let a = b; // Block-scoped variable 'b' used before its declaration + ~ +!!! error TS2448: Block-scoped variable 'b' used before its declaration. + let b = 3; + } + } + \ No newline at end of file diff --git a/tests/baselines/reference/forwardRefInClassProperties.js b/tests/baselines/reference/forwardRefInClassProperties.js new file mode 100644 index 00000000000..1dc455729ab --- /dev/null +++ b/tests/baselines/reference/forwardRefInClassProperties.js @@ -0,0 +1,31 @@ +//// [forwardRefInClassProperties.ts] +class Test +{ + _b = this._a; // undefined, no error/warning + _a = 3; + + static _B = Test._A; // undefined, no error/warning + static _A = 3; + + method() + { + let a = b; // Block-scoped variable 'b' used before its declaration + let b = 3; + } +} + + +//// [forwardRefInClassProperties.js] +var Test = (function () { + function Test() { + this._b = this._a; // undefined, no error/warning + this._a = 3; + } + Test.prototype.method = function () { + var a = b; // Block-scoped variable 'b' used before its declaration + var b = 3; + }; + return Test; +}()); +Test._B = Test._A; // undefined, no error/warning +Test._A = 3; diff --git a/tests/cases/compiler/forwardRefInClassProperties.ts b/tests/cases/compiler/forwardRefInClassProperties.ts new file mode 100644 index 00000000000..80819b1a175 --- /dev/null +++ b/tests/cases/compiler/forwardRefInClassProperties.ts @@ -0,0 +1,14 @@ +class Test +{ + _b = this._a; // undefined, no error/warning + _a = 3; + + static _B = Test._A; // undefined, no error/warning + static _A = 3; + + method() + { + let a = b; // Block-scoped variable 'b' used before its declaration + let b = 3; + } +} From 188e9df9b55d15b003852632c14425ffe92823e5 Mon Sep 17 00:00:00 2001 From: Kanchalai Tanglertsampan Date: Mon, 6 Feb 2017 18:13:17 -0800 Subject: [PATCH 43/58] Emit missing trailing comment of an element in node list --- src/compiler/comments.ts | 6 ++++++ src/compiler/emitter.ts | 24 ++++++++++++++++++++++++ 2 files changed, 30 insertions(+) diff --git a/src/compiler/comments.ts b/src/compiler/comments.ts index 200158c2f5c..8e17bf2d91b 100644 --- a/src/compiler/comments.ts +++ b/src/compiler/comments.ts @@ -9,6 +9,7 @@ namespace ts { emitNodeWithComments(hint: EmitHint, node: Node, emitCallback: (hint: EmitHint, node: Node) => void): void; emitBodyWithDetachedComments(node: Node, detachedRange: TextRange, emitCallback: (node: Node) => void): void; emitTrailingCommentsOfPosition(pos: number): void; + emitLeadingComments(pos: number, isEmittedNode: boolean): void; } export function createCommentWriter(printerOptions: PrinterOptions, emitPos: ((pos: number) => void) | undefined): CommentWriter { @@ -32,6 +33,7 @@ namespace ts { emitNodeWithComments, emitBodyWithDetachedComments, emitTrailingCommentsOfPosition, + emitLeadingComments, }; function emitNodeWithComments(hint: EmitHint, node: Node, emitCallback: (hint: EmitHint, node: Node) => void) { @@ -167,6 +169,10 @@ namespace ts { } function emitLeadingComments(pos: number, isEmittedNode: boolean) { + if (disabled) { + return; + } + hasWrittenComment = false; if (isEmittedNode) { diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index 498f65ad366..d3e46f0827d 100644 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -211,6 +211,7 @@ namespace ts { emitNodeWithComments, emitBodyWithDetachedComments, emitTrailingCommentsOfPosition, + emitLeadingComments, } = comments; let currentSourceFile: SourceFile; @@ -2228,6 +2229,15 @@ namespace ts { // Write the delimiter if this is not the first node. if (previousSibling) { + // i.e + // function commentedParameters( + // /* Parameter a */ + // a + // /* End of parameter a */ -> this comment doesn't consider to be trailing comment of parameter "a" due to newline + // , + if (emitLeadingComments && delimiter && previousSibling.end !== parentNode.end) { + emitLeadingComments(previousSibling.end, /*isEmittedNode*/ previousSibling.kind !== SyntaxKind.NotEmittedStatement); + } write(delimiter); // Write either a line terminator or whitespace to separate the elements. @@ -2274,6 +2284,20 @@ namespace ts { write(","); } + + // Emit any trailing comment of the last element in the list + // i.e + // var array = [... + // 2 + // /* end of element 2 */ + // ]; + if (previousSibling && delimiter && previousSibling.end !== parentNode.end) { + emitLeadingComments(previousSibling.end, /*isEmittedNode*/ previousSibling.kind !== SyntaxKind.NotEmittedStatement); + if (hasTrailingComma) { + emitLeadingComments(previousSibling.end, /*isEmittedNode*/ previousSibling.kind !== SyntaxKind.NotEmittedStatement); + } + } + // Decrease the indent, if requested. if (format & ListFormat.Indented) { decreaseIndent(); From 7fd404dbbc20611bca81f8cde3a07c91e69ee13f Mon Sep 17 00:00:00 2001 From: Kanchalai Tanglertsampan Date: Mon, 6 Feb 2017 18:14:08 -0800 Subject: [PATCH 44/58] Add tests and update baselines --- .../reference/arrowFunctionErrorSpan.js | 4 +++- .../reference/commentOnArrayElement1.js | 17 ++++++++++++++++ .../reference/commentOnArrayElement1.symbols | 10 ++++++++++ .../reference/commentOnArrayElement1.types | 15 ++++++++++++++ .../reference/commentOnArrayElement2.js | 15 ++++++++++++++ .../reference/commentOnArrayElement2.symbols | 9 +++++++++ .../reference/commentOnArrayElement2.types | 14 +++++++++++++ .../reference/commentOnArrayElement3.js | 19 ++++++++++++++++++ .../reference/commentOnArrayElement3.symbols | 11 ++++++++++ .../reference/commentOnArrayElement3.types | 18 +++++++++++++++++ .../reference/commentOnParameter1.js | 20 +++++++++++++++++++ .../reference/commentOnParameter1.symbols | 16 +++++++++++++++ .../reference/commentOnParameter1.types | 16 +++++++++++++++ .../reference/commentOnParameter2.js | 18 +++++++++++++++++ .../reference/commentOnParameter2.symbols | 15 ++++++++++++++ .../reference/commentOnParameter2.types | 15 ++++++++++++++ .../reference/commentOnParameter3.js | 9 +++++++++ .../reference/commentOnParameter3.symbols | 12 +++++++++++ .../reference/commentOnParameter3.types | 12 +++++++++++ .../cases/compiler/commentOnArrayElement1.ts | 7 +++++++ .../cases/compiler/commentOnArrayElement2.ts | 6 ++++++ .../cases/compiler/commentOnArrayElement3.ts | 8 ++++++++ tests/cases/compiler/commentOnParameter1.ts | 9 +++++++++ tests/cases/compiler/commentOnParameter2.ts | 8 ++++++++ tests/cases/compiler/commentOnParameter3.ts | 5 +++++ 25 files changed, 307 insertions(+), 1 deletion(-) create mode 100644 tests/baselines/reference/commentOnArrayElement1.js create mode 100644 tests/baselines/reference/commentOnArrayElement1.symbols create mode 100644 tests/baselines/reference/commentOnArrayElement1.types create mode 100644 tests/baselines/reference/commentOnArrayElement2.js create mode 100644 tests/baselines/reference/commentOnArrayElement2.symbols create mode 100644 tests/baselines/reference/commentOnArrayElement2.types create mode 100644 tests/baselines/reference/commentOnArrayElement3.js create mode 100644 tests/baselines/reference/commentOnArrayElement3.symbols create mode 100644 tests/baselines/reference/commentOnArrayElement3.types create mode 100644 tests/baselines/reference/commentOnParameter1.js create mode 100644 tests/baselines/reference/commentOnParameter1.symbols create mode 100644 tests/baselines/reference/commentOnParameter1.types create mode 100644 tests/baselines/reference/commentOnParameter2.js create mode 100644 tests/baselines/reference/commentOnParameter2.symbols create mode 100644 tests/baselines/reference/commentOnParameter2.types create mode 100644 tests/baselines/reference/commentOnParameter3.js create mode 100644 tests/baselines/reference/commentOnParameter3.symbols create mode 100644 tests/baselines/reference/commentOnParameter3.types create mode 100644 tests/cases/compiler/commentOnArrayElement1.ts create mode 100644 tests/cases/compiler/commentOnArrayElement2.ts create mode 100644 tests/cases/compiler/commentOnArrayElement3.ts create mode 100644 tests/cases/compiler/commentOnParameter1.ts create mode 100644 tests/cases/compiler/commentOnParameter2.ts create mode 100644 tests/cases/compiler/commentOnParameter3.ts diff --git a/tests/baselines/reference/arrowFunctionErrorSpan.js b/tests/baselines/reference/arrowFunctionErrorSpan.js index 2557113e89b..ca1f966f517 100644 --- a/tests/baselines/reference/arrowFunctionErrorSpan.js +++ b/tests/baselines/reference/arrowFunctionErrorSpan.js @@ -83,7 +83,9 @@ f(// comment 1 // comment 2 function () { // comment 4 -}); +} +// comment 5 +); // body is not a block f(function (_) { return 1 + 2; }); diff --git a/tests/baselines/reference/commentOnArrayElement1.js b/tests/baselines/reference/commentOnArrayElement1.js new file mode 100644 index 00000000000..960df336dbb --- /dev/null +++ b/tests/baselines/reference/commentOnArrayElement1.js @@ -0,0 +1,17 @@ +//// [commentOnArrayElement1.ts] +var array = [ + /* element 1*/ + 1 + /* end of element 1 */, + 2 + /* end of element 2 */ +]; + +//// [commentOnArrayElement1.js] +var array = [ + /* element 1*/ + 1 + /* end of element 1 */ , + 2 + /* end of element 2 */ +]; diff --git a/tests/baselines/reference/commentOnArrayElement1.symbols b/tests/baselines/reference/commentOnArrayElement1.symbols new file mode 100644 index 00000000000..a504aec5c32 --- /dev/null +++ b/tests/baselines/reference/commentOnArrayElement1.symbols @@ -0,0 +1,10 @@ +=== tests/cases/compiler/commentOnArrayElement1.ts === +var array = [ +>array : Symbol(array, Decl(commentOnArrayElement1.ts, 0, 3)) + + /* element 1*/ + 1 + /* end of element 1 */, + 2 + /* end of element 2 */ +]; diff --git a/tests/baselines/reference/commentOnArrayElement1.types b/tests/baselines/reference/commentOnArrayElement1.types new file mode 100644 index 00000000000..f6b541ec300 --- /dev/null +++ b/tests/baselines/reference/commentOnArrayElement1.types @@ -0,0 +1,15 @@ +=== tests/cases/compiler/commentOnArrayElement1.ts === +var array = [ +>array : number[] +>[ /* element 1*/ 1 /* end of element 1 */, 2 /* end of element 2 */] : number[] + + /* element 1*/ + 1 +>1 : 1 + + /* end of element 1 */, + 2 +>2 : 2 + + /* end of element 2 */ +]; diff --git a/tests/baselines/reference/commentOnArrayElement2.js b/tests/baselines/reference/commentOnArrayElement2.js new file mode 100644 index 00000000000..1c146caed65 --- /dev/null +++ b/tests/baselines/reference/commentOnArrayElement2.js @@ -0,0 +1,15 @@ +//// [commentOnArrayElement2.ts] +var array = [ + /* element 1*/ + 1 /* end of element 1 */, + 2 + /* end of element 2 */ +]; + +//// [commentOnArrayElement2.js] +var array = [ + /* element 1*/ + 1 /* end of element 1 */, + 2 + /* end of element 2 */ +]; diff --git a/tests/baselines/reference/commentOnArrayElement2.symbols b/tests/baselines/reference/commentOnArrayElement2.symbols new file mode 100644 index 00000000000..7a6c231664b --- /dev/null +++ b/tests/baselines/reference/commentOnArrayElement2.symbols @@ -0,0 +1,9 @@ +=== tests/cases/compiler/commentOnArrayElement2.ts === +var array = [ +>array : Symbol(array, Decl(commentOnArrayElement2.ts, 0, 3)) + + /* element 1*/ + 1 /* end of element 1 */, + 2 + /* end of element 2 */ +]; diff --git a/tests/baselines/reference/commentOnArrayElement2.types b/tests/baselines/reference/commentOnArrayElement2.types new file mode 100644 index 00000000000..85647da74e0 --- /dev/null +++ b/tests/baselines/reference/commentOnArrayElement2.types @@ -0,0 +1,14 @@ +=== tests/cases/compiler/commentOnArrayElement2.ts === +var array = [ +>array : number[] +>[ /* element 1*/ 1 /* end of element 1 */, 2 /* end of element 2 */] : number[] + + /* element 1*/ + 1 /* end of element 1 */, +>1 : 1 + + 2 +>2 : 2 + + /* end of element 2 */ +]; diff --git a/tests/baselines/reference/commentOnArrayElement3.js b/tests/baselines/reference/commentOnArrayElement3.js new file mode 100644 index 00000000000..e31f8adf26a --- /dev/null +++ b/tests/baselines/reference/commentOnArrayElement3.js @@ -0,0 +1,19 @@ +//// [commentOnArrayElement3.ts] +var array = [ + /* element 1*/ + 1 + /* end of element 1 */, + 2 + /* end of element 2 */, , + /* extra comment */ +]; + +//// [commentOnArrayElement3.js] +var array = [ + /* element 1*/ + 1 + /* end of element 1 */ , + 2 + /* end of element 2 */ , + , +]; diff --git a/tests/baselines/reference/commentOnArrayElement3.symbols b/tests/baselines/reference/commentOnArrayElement3.symbols new file mode 100644 index 00000000000..a1c61f7155a --- /dev/null +++ b/tests/baselines/reference/commentOnArrayElement3.symbols @@ -0,0 +1,11 @@ +=== tests/cases/compiler/commentOnArrayElement3.ts === +var array = [ +>array : Symbol(array, Decl(commentOnArrayElement3.ts, 0, 3)) + + /* element 1*/ + 1 + /* end of element 1 */, + 2 + /* end of element 2 */, , + /* extra comment */ +]; diff --git a/tests/baselines/reference/commentOnArrayElement3.types b/tests/baselines/reference/commentOnArrayElement3.types new file mode 100644 index 00000000000..cd75c5a8db9 --- /dev/null +++ b/tests/baselines/reference/commentOnArrayElement3.types @@ -0,0 +1,18 @@ +=== tests/cases/compiler/commentOnArrayElement3.ts === +var array = [ +>array : number[] +>[ /* element 1*/ 1 /* end of element 1 */, 2 /* end of element 2 */, , /* extra comment */] : number[] + + /* element 1*/ + 1 +>1 : 1 + + /* end of element 1 */, + 2 +>2 : 2 + + /* end of element 2 */, , +> : undefined + + /* extra comment */ +]; diff --git a/tests/baselines/reference/commentOnParameter1.js b/tests/baselines/reference/commentOnParameter1.js new file mode 100644 index 00000000000..10ae2af1264 --- /dev/null +++ b/tests/baselines/reference/commentOnParameter1.js @@ -0,0 +1,20 @@ +//// [commentOnParameter1.ts] +function commentedParameters( +/* Parameter a */ +a +/* End of parameter a */ +/* Parameter b */ +, +b +/* End of parameter b */ +){} + +//// [commentOnParameter1.js] +function commentedParameters( + /* Parameter a */ + a + /* End of parameter a */ + /* Parameter b */ + , b + /* End of parameter b */ +) { } diff --git a/tests/baselines/reference/commentOnParameter1.symbols b/tests/baselines/reference/commentOnParameter1.symbols new file mode 100644 index 00000000000..13d91ac7abb --- /dev/null +++ b/tests/baselines/reference/commentOnParameter1.symbols @@ -0,0 +1,16 @@ +=== tests/cases/compiler/commentOnParameter1.ts === +function commentedParameters( +>commentedParameters : Symbol(commentedParameters, Decl(commentOnParameter1.ts, 0, 0)) + +/* Parameter a */ +a +>a : Symbol(a, Decl(commentOnParameter1.ts, 0, 29)) + +/* End of parameter a */ +/* Parameter b */ +, +b +>b : Symbol(b, Decl(commentOnParameter1.ts, 5, 1)) + +/* End of parameter b */ +){} diff --git a/tests/baselines/reference/commentOnParameter1.types b/tests/baselines/reference/commentOnParameter1.types new file mode 100644 index 00000000000..2a98a9a3f6f --- /dev/null +++ b/tests/baselines/reference/commentOnParameter1.types @@ -0,0 +1,16 @@ +=== tests/cases/compiler/commentOnParameter1.ts === +function commentedParameters( +>commentedParameters : (a: any, b: any) => void + +/* Parameter a */ +a +>a : any + +/* End of parameter a */ +/* Parameter b */ +, +b +>b : any + +/* End of parameter b */ +){} diff --git a/tests/baselines/reference/commentOnParameter2.js b/tests/baselines/reference/commentOnParameter2.js new file mode 100644 index 00000000000..d0c024a6b3b --- /dev/null +++ b/tests/baselines/reference/commentOnParameter2.js @@ -0,0 +1,18 @@ +//// [commentOnParameter2.ts] +function commentedParameters( +/* Parameter a */ +a /* End of parameter a */ +/* Parameter b */ +, +b +/* End of parameter b */ +){} + +//// [commentOnParameter2.js] +function commentedParameters( + /* Parameter a */ + a /* End of parameter a */ + /* Parameter b */ + , b + /* End of parameter b */ +) { } diff --git a/tests/baselines/reference/commentOnParameter2.symbols b/tests/baselines/reference/commentOnParameter2.symbols new file mode 100644 index 00000000000..5a6e904ed0b --- /dev/null +++ b/tests/baselines/reference/commentOnParameter2.symbols @@ -0,0 +1,15 @@ +=== tests/cases/compiler/commentOnParameter2.ts === +function commentedParameters( +>commentedParameters : Symbol(commentedParameters, Decl(commentOnParameter2.ts, 0, 0)) + +/* Parameter a */ +a /* End of parameter a */ +>a : Symbol(a, Decl(commentOnParameter2.ts, 0, 29)) + +/* Parameter b */ +, +b +>b : Symbol(b, Decl(commentOnParameter2.ts, 4, 1)) + +/* End of parameter b */ +){} diff --git a/tests/baselines/reference/commentOnParameter2.types b/tests/baselines/reference/commentOnParameter2.types new file mode 100644 index 00000000000..2d4c14db809 --- /dev/null +++ b/tests/baselines/reference/commentOnParameter2.types @@ -0,0 +1,15 @@ +=== tests/cases/compiler/commentOnParameter2.ts === +function commentedParameters( +>commentedParameters : (a: any, b: any) => void + +/* Parameter a */ +a /* End of parameter a */ +>a : any + +/* Parameter b */ +, +b +>b : any + +/* End of parameter b */ +){} diff --git a/tests/baselines/reference/commentOnParameter3.js b/tests/baselines/reference/commentOnParameter3.js new file mode 100644 index 00000000000..56172af473c --- /dev/null +++ b/tests/baselines/reference/commentOnParameter3.js @@ -0,0 +1,9 @@ +//// [commentOnParameter3.ts] +function commentedParameters( +a /* parameter a */, +b /* parameter b */, +/* extra comment */ +) { } + +//// [commentOnParameter3.js] +function commentedParameters(a /* parameter a */, b /* parameter b */) { } diff --git a/tests/baselines/reference/commentOnParameter3.symbols b/tests/baselines/reference/commentOnParameter3.symbols new file mode 100644 index 00000000000..4dda5f6d0e8 --- /dev/null +++ b/tests/baselines/reference/commentOnParameter3.symbols @@ -0,0 +1,12 @@ +=== tests/cases/compiler/commentOnParameter3.ts === +function commentedParameters( +>commentedParameters : Symbol(commentedParameters, Decl(commentOnParameter3.ts, 0, 0)) + +a /* parameter a */, +>a : Symbol(a, Decl(commentOnParameter3.ts, 0, 29)) + +b /* parameter b */, +>b : Symbol(b, Decl(commentOnParameter3.ts, 1, 20)) + +/* extra comment */ +) { } diff --git a/tests/baselines/reference/commentOnParameter3.types b/tests/baselines/reference/commentOnParameter3.types new file mode 100644 index 00000000000..f5b23dbceb3 --- /dev/null +++ b/tests/baselines/reference/commentOnParameter3.types @@ -0,0 +1,12 @@ +=== tests/cases/compiler/commentOnParameter3.ts === +function commentedParameters( +>commentedParameters : (a: any, b: any) => void + +a /* parameter a */, +>a : any + +b /* parameter b */, +>b : any + +/* extra comment */ +) { } diff --git a/tests/cases/compiler/commentOnArrayElement1.ts b/tests/cases/compiler/commentOnArrayElement1.ts new file mode 100644 index 00000000000..3dc4ce29bf1 --- /dev/null +++ b/tests/cases/compiler/commentOnArrayElement1.ts @@ -0,0 +1,7 @@ +var array = [ + /* element 1*/ + 1 + /* end of element 1 */, + 2 + /* end of element 2 */ +]; \ No newline at end of file diff --git a/tests/cases/compiler/commentOnArrayElement2.ts b/tests/cases/compiler/commentOnArrayElement2.ts new file mode 100644 index 00000000000..80c7f8fb1a7 --- /dev/null +++ b/tests/cases/compiler/commentOnArrayElement2.ts @@ -0,0 +1,6 @@ +var array = [ + /* element 1*/ + 1 /* end of element 1 */, + 2 + /* end of element 2 */ +]; \ No newline at end of file diff --git a/tests/cases/compiler/commentOnArrayElement3.ts b/tests/cases/compiler/commentOnArrayElement3.ts new file mode 100644 index 00000000000..26de853f3e9 --- /dev/null +++ b/tests/cases/compiler/commentOnArrayElement3.ts @@ -0,0 +1,8 @@ +var array = [ + /* element 1*/ + 1 + /* end of element 1 */, + 2 + /* end of element 2 */, , + /* extra comment */ +]; \ No newline at end of file diff --git a/tests/cases/compiler/commentOnParameter1.ts b/tests/cases/compiler/commentOnParameter1.ts new file mode 100644 index 00000000000..6a17c90950c --- /dev/null +++ b/tests/cases/compiler/commentOnParameter1.ts @@ -0,0 +1,9 @@ +function commentedParameters( +/* Parameter a */ +a +/* End of parameter a */ +/* Parameter b */ +, +b +/* End of parameter b */ +){} \ No newline at end of file diff --git a/tests/cases/compiler/commentOnParameter2.ts b/tests/cases/compiler/commentOnParameter2.ts new file mode 100644 index 00000000000..2722eab554b --- /dev/null +++ b/tests/cases/compiler/commentOnParameter2.ts @@ -0,0 +1,8 @@ +function commentedParameters( +/* Parameter a */ +a /* End of parameter a */ +/* Parameter b */ +, +b +/* End of parameter b */ +){} \ No newline at end of file diff --git a/tests/cases/compiler/commentOnParameter3.ts b/tests/cases/compiler/commentOnParameter3.ts new file mode 100644 index 00000000000..57eda10f338 --- /dev/null +++ b/tests/cases/compiler/commentOnParameter3.ts @@ -0,0 +1,5 @@ +function commentedParameters( +a /* parameter a */, +b /* parameter b */, +/* extra comment */ +) { } \ No newline at end of file From a7728f8fa133513200e2e5f6136810e463b1aa4f Mon Sep 17 00:00:00 2001 From: Ron Buckton Date: Tue, 7 Feb 2017 11:24:05 -0800 Subject: [PATCH 45/58] Clean up extraneous file --- src/services/transform.ts | 29 ----------------------------- 1 file changed, 29 deletions(-) delete mode 100644 src/services/transform.ts diff --git a/src/services/transform.ts b/src/services/transform.ts deleted file mode 100644 index c9107eea853..00000000000 --- a/src/services/transform.ts +++ /dev/null @@ -1,29 +0,0 @@ -/// -/// -namespace ts { - /** - * Transform one or more source files using the supplied transformers. - * @param source A `SourceFile` or an array of `SourceFiles`. - * @param transformers An array of `Transformer` callbacks used to process the transformation. - */ - export function transform(source: SourceFile | SourceFile[], transformers: Transformer[]) { - const diagnostics: Diagnostic[] = []; - const compilerOptions: CompilerOptions = {}; - const sourceFiles = isArray(source) ? source : [source]; - const fileMap = arrayToMap(sourceFiles, sourceFile => sourceFile.fileName); - const emitHost: EmitHost = { - getCompilerOptions: () => compilerOptions, - getCanonicalFileName: fileName => fileName, - getCommonSourceDirectory: () => "", - getCurrentDirectory: () => "", - getNewLine: () => "\n", - getSourceFile: fileName => fileMap.get(fileName), - getSourceFileByPath: fileName => fileMap.get(fileName), - getSourceFiles: () => sourceFiles, - isSourceFileFromExternalLibrary: () => false, - isEmitBlocked: () => false, - writeFile: () => Debug.fail("'writeFile()' is not supported during transformation.") - }; - return transformFiles(/*resolver*/ undefined, emitHost, sourceFiles, transformers); - } -} \ No newline at end of file From 80eae169ee2d2b114ed25f9af275923f5e4c511f Mon Sep 17 00:00:00 2001 From: Kanchalai Tanglertsampan Date: Tue, 7 Feb 2017 11:56:44 -0800 Subject: [PATCH 46/58] Emit leading comment before brace token --- src/compiler/emitter.ts | 2 ++ .../reference/amdImportAsPrimaryExpression.js | 1 + tests/baselines/reference/argsInScope.js | 1 + .../reference/commentLeadingCloseBrace.js | 24 +++++++++++++ .../commentLeadingCloseBrace.symbols | 21 ++++++++++++ .../reference/commentLeadingCloseBrace.types | 30 ++++++++++++++++ .../commonJSImportAsPrimaryExpression.js | 1 + .../reference/duplicateLocalVariable1.js | 1 + .../jsFileCompilationLetBeingRenamed.js | 1 + .../narrowExceptionVariableInCatchClause.js | 1 + tests/baselines/reference/noCatchBlock.js | 2 ++ tests/baselines/reference/noCatchBlock.js.map | 2 +- .../reference/noCatchBlock.sourcemap.txt | 34 ++++++++++++++----- tests/baselines/reference/objectRestForOf.js | 1 + .../baselines/reference/parserRealSource14.js | 1 + tests/baselines/reference/recursiveReturns.js | 1 + .../reference/sourceMap-SkippedNode.js | 2 ++ .../reference/sourceMap-SkippedNode.js.map | 2 +- .../sourceMap-SkippedNode.sourcemap.txt | 34 ++++++++++++++----- .../compiler/commentLeadingCloseBrace.ts | 11 ++++++ 20 files changed, 155 insertions(+), 18 deletions(-) create mode 100644 tests/baselines/reference/commentLeadingCloseBrace.js create mode 100644 tests/baselines/reference/commentLeadingCloseBrace.symbols create mode 100644 tests/baselines/reference/commentLeadingCloseBrace.types create mode 100644 tests/cases/compiler/commentLeadingCloseBrace.ts diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index d3e46f0827d..7adac106e8c 100644 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -1347,6 +1347,8 @@ namespace ts { else { writeToken(SyntaxKind.OpenBraceToken, node.pos, /*contextNode*/ node); emitBlockStatements(node); + // We have to call emitLeadingComments explicitly here because otherwise leading comments of the close brace token will not be emitted + emitLeadingComments(node.statements.end, /*isEmittedNode*/true); writeToken(SyntaxKind.CloseBraceToken, node.statements.end, /*contextNode*/ node); } } diff --git a/tests/baselines/reference/amdImportAsPrimaryExpression.js b/tests/baselines/reference/amdImportAsPrimaryExpression.js index 3c2e9c041fa..25f390c0b32 100644 --- a/tests/baselines/reference/amdImportAsPrimaryExpression.js +++ b/tests/baselines/reference/amdImportAsPrimaryExpression.js @@ -26,5 +26,6 @@ define(["require", "exports"], function (require, exports) { define(["require", "exports", "./foo_0"], function (require, exports, foo) { "use strict"; if (foo.E1.A === 0) { + // Should cause runtime import - interesting optimization possibility, as gets inlined to 0. } }); diff --git a/tests/baselines/reference/argsInScope.js b/tests/baselines/reference/argsInScope.js index 90906426d24..27405a47d87 100644 --- a/tests/baselines/reference/argsInScope.js +++ b/tests/baselines/reference/argsInScope.js @@ -17,6 +17,7 @@ var C = (function () { } C.prototype.P = function (ii, j, k) { for (var i = 0; i < arguments.length; i++) { + // WScript.Echo("param: " + arguments[i]); } }; return C; diff --git a/tests/baselines/reference/commentLeadingCloseBrace.js b/tests/baselines/reference/commentLeadingCloseBrace.js new file mode 100644 index 00000000000..9fc696219e1 --- /dev/null +++ b/tests/baselines/reference/commentLeadingCloseBrace.js @@ -0,0 +1,24 @@ +//// [commentLeadingCloseBrace.ts] +declare function commentedParameters(...args): any; + +function ifelse() { + if (commentedParameters(1, 2)) { + /*comment1*/ + commentedParameters(3, 4); + /*comment2*/ + } else { + commentedParameters(5, 6); + } +} + +//// [commentLeadingCloseBrace.js] +function ifelse() { + if (commentedParameters(1, 2)) { + /*comment1*/ + commentedParameters(3, 4); + /*comment2*/ + } + else { + commentedParameters(5, 6); + } +} diff --git a/tests/baselines/reference/commentLeadingCloseBrace.symbols b/tests/baselines/reference/commentLeadingCloseBrace.symbols new file mode 100644 index 00000000000..72dcfb1e047 --- /dev/null +++ b/tests/baselines/reference/commentLeadingCloseBrace.symbols @@ -0,0 +1,21 @@ +=== tests/cases/compiler/commentLeadingCloseBrace.ts === +declare function commentedParameters(...args): any; +>commentedParameters : Symbol(commentedParameters, Decl(commentLeadingCloseBrace.ts, 0, 0)) +>args : Symbol(args, Decl(commentLeadingCloseBrace.ts, 0, 37)) + +function ifelse() { +>ifelse : Symbol(ifelse, Decl(commentLeadingCloseBrace.ts, 0, 51)) + + if (commentedParameters(1, 2)) { +>commentedParameters : Symbol(commentedParameters, Decl(commentLeadingCloseBrace.ts, 0, 0)) + + /*comment1*/ + commentedParameters(3, 4); +>commentedParameters : Symbol(commentedParameters, Decl(commentLeadingCloseBrace.ts, 0, 0)) + + /*comment2*/ + } else { + commentedParameters(5, 6); +>commentedParameters : Symbol(commentedParameters, Decl(commentLeadingCloseBrace.ts, 0, 0)) + } +} diff --git a/tests/baselines/reference/commentLeadingCloseBrace.types b/tests/baselines/reference/commentLeadingCloseBrace.types new file mode 100644 index 00000000000..444320737a6 --- /dev/null +++ b/tests/baselines/reference/commentLeadingCloseBrace.types @@ -0,0 +1,30 @@ +=== tests/cases/compiler/commentLeadingCloseBrace.ts === +declare function commentedParameters(...args): any; +>commentedParameters : (...args: any[]) => any +>args : any[] + +function ifelse() { +>ifelse : () => void + + if (commentedParameters(1, 2)) { +>commentedParameters(1, 2) : any +>commentedParameters : (...args: any[]) => any +>1 : 1 +>2 : 2 + + /*comment1*/ + commentedParameters(3, 4); +>commentedParameters(3, 4) : any +>commentedParameters : (...args: any[]) => any +>3 : 3 +>4 : 4 + + /*comment2*/ + } else { + commentedParameters(5, 6); +>commentedParameters(5, 6) : any +>commentedParameters : (...args: any[]) => any +>5 : 5 +>6 : 6 + } +} diff --git a/tests/baselines/reference/commonJSImportAsPrimaryExpression.js b/tests/baselines/reference/commonJSImportAsPrimaryExpression.js index b8cf42ea762..1eb7b5ff214 100644 --- a/tests/baselines/reference/commonJSImportAsPrimaryExpression.js +++ b/tests/baselines/reference/commonJSImportAsPrimaryExpression.js @@ -27,4 +27,5 @@ exports.C1 = C1; "use strict"; var foo = require("./foo_0"); if (foo.C1.s1) { +// Should cause runtime import } diff --git a/tests/baselines/reference/duplicateLocalVariable1.js b/tests/baselines/reference/duplicateLocalVariable1.js index 734b01eaed7..432830d85b6 100644 --- a/tests/baselines/reference/duplicateLocalVariable1.js +++ b/tests/baselines/reference/duplicateLocalVariable1.js @@ -391,6 +391,7 @@ var TestRunner = (function () { } } if (testResult === false) { + //console.log(e.message); } } if ((testcase.errorMessageRegEx !== undefined) && !exception) { diff --git a/tests/baselines/reference/jsFileCompilationLetBeingRenamed.js b/tests/baselines/reference/jsFileCompilationLetBeingRenamed.js index c9e16f35981..bb2aa10dc95 100644 --- a/tests/baselines/reference/jsFileCompilationLetBeingRenamed.js +++ b/tests/baselines/reference/jsFileCompilationLetBeingRenamed.js @@ -9,5 +9,6 @@ function foo(a) { //// [out.js] function foo(a) { for (var a_1 = 0; a_1 < 10; a_1++) { + // do something } } diff --git a/tests/baselines/reference/narrowExceptionVariableInCatchClause.js b/tests/baselines/reference/narrowExceptionVariableInCatchClause.js index 5808ed76826..18344df5994 100644 --- a/tests/baselines/reference/narrowExceptionVariableInCatchClause.js +++ b/tests/baselines/reference/narrowExceptionVariableInCatchClause.js @@ -27,6 +27,7 @@ function tryCatch() { //// [narrowExceptionVariableInCatchClause.js] function tryCatch() { try { + // do stuff... } catch (err) { if (isFooError(err)) { diff --git a/tests/baselines/reference/noCatchBlock.js b/tests/baselines/reference/noCatchBlock.js index 7b0404c3cad..158ac1257f3 100644 --- a/tests/baselines/reference/noCatchBlock.js +++ b/tests/baselines/reference/noCatchBlock.js @@ -8,7 +8,9 @@ try { //// [noCatchBlock.js] try { +// ... } finally { +// N.B. No 'catch' block } //# sourceMappingURL=noCatchBlock.js.map \ No newline at end of file diff --git a/tests/baselines/reference/noCatchBlock.js.map b/tests/baselines/reference/noCatchBlock.js.map index 149a2167f46..ddac2894e0b 100644 --- a/tests/baselines/reference/noCatchBlock.js.map +++ b/tests/baselines/reference/noCatchBlock.js.map @@ -1,2 +1,2 @@ //// [noCatchBlock.js.map] -{"version":3,"file":"noCatchBlock.js","sourceRoot":"","sources":["noCatchBlock.ts"],"names":[],"mappings":"AACA,IAAI,CAAC;AAEL,CAAC;QAAS,CAAC;AAEX,CAAC"} \ No newline at end of file +{"version":3,"file":"noCatchBlock.js","sourceRoot":"","sources":["noCatchBlock.ts"],"names":[],"mappings":"AACA,IAAI,CAAC;AACJ,MAAM;AACP,CAAC;QAAS,CAAC;AACV,wBAAwB;AACzB,CAAC"} \ No newline at end of file diff --git a/tests/baselines/reference/noCatchBlock.sourcemap.txt b/tests/baselines/reference/noCatchBlock.sourcemap.txt index 18cb0d5a479..a75c119ca9f 100644 --- a/tests/baselines/reference/noCatchBlock.sourcemap.txt +++ b/tests/baselines/reference/noCatchBlock.sourcemap.txt @@ -12,6 +12,7 @@ sourceFile:noCatchBlock.ts 1 > 2 >^^^^ 3 > ^ +4 > ^^-> 1 > > 2 >try @@ -20,34 +21,51 @@ sourceFile:noCatchBlock.ts 2 >Emitted(1, 5) Source(2, 5) + SourceIndex(0) 3 >Emitted(1, 6) Source(2, 6) + SourceIndex(0) --- +>>>// ... +1-> +2 >^^^^^^ +1-> + > +2 >// ... +1->Emitted(2, 1) Source(3, 2) + SourceIndex(0) +2 >Emitted(2, 7) Source(3, 8) + SourceIndex(0) +--- >>>} 1 > 2 >^ 3 > ^^^^^^^^^-> 1 > - > // ... > 2 >} -1 >Emitted(2, 1) Source(4, 1) + SourceIndex(0) -2 >Emitted(2, 2) Source(4, 2) + SourceIndex(0) +1 >Emitted(3, 1) Source(4, 1) + SourceIndex(0) +2 >Emitted(3, 2) Source(4, 2) + SourceIndex(0) --- >>>finally { 1->^^^^^^^^ 2 > ^ +3 > ^^^^^^^^^^^^^^^^-> 1-> finally 2 > { -1->Emitted(3, 9) Source(4, 11) + SourceIndex(0) -2 >Emitted(3, 10) Source(4, 12) + SourceIndex(0) +1->Emitted(4, 9) Source(4, 11) + SourceIndex(0) +2 >Emitted(4, 10) Source(4, 12) + SourceIndex(0) +--- +>>>// N.B. No 'catch' block +1-> +2 >^^^^^^^^^^^^^^^^^^^^^^^^ +1-> + > +2 >// N.B. No 'catch' block +1->Emitted(5, 1) Source(5, 2) + SourceIndex(0) +2 >Emitted(5, 25) Source(5, 26) + SourceIndex(0) --- >>>} 1 > 2 >^ 3 > ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-> 1 > - > // N.B. No 'catch' block > 2 >} -1 >Emitted(4, 1) Source(6, 1) + SourceIndex(0) -2 >Emitted(4, 2) Source(6, 2) + SourceIndex(0) +1 >Emitted(6, 1) Source(6, 1) + SourceIndex(0) +2 >Emitted(6, 2) Source(6, 2) + SourceIndex(0) --- >>>//# sourceMappingURL=noCatchBlock.js.map \ No newline at end of file diff --git a/tests/baselines/reference/objectRestForOf.js b/tests/baselines/reference/objectRestForOf.js index f8a88fe2868..5f0399b2df2 100644 --- a/tests/baselines/reference/objectRestForOf.js +++ b/tests/baselines/reference/objectRestForOf.js @@ -37,4 +37,5 @@ for (let _b of array) { } for (const norest of array.map(a => (Object.assign({}, a, { x: 'a string' })))) { [norest.x, norest.y]; +// x is now a string. who knows why. } diff --git a/tests/baselines/reference/parserRealSource14.js b/tests/baselines/reference/parserRealSource14.js index 907efc6f26a..4e4e23e81c3 100644 --- a/tests/baselines/reference/parserRealSource14.js +++ b/tests/baselines/reference/parserRealSource14.js @@ -1011,6 +1011,7 @@ var TypeScript; ctx.path.push(cur); } else { + //logger.log("TODO: Ignoring node because minChar, limChar not better than previous node in stack"); } } // The AST walker skips comments, but we might be in one, so check the pre/post comments for this node manually diff --git a/tests/baselines/reference/recursiveReturns.js b/tests/baselines/reference/recursiveReturns.js index 18c9ed4dd7c..56762a9ad2d 100644 --- a/tests/baselines/reference/recursiveReturns.js +++ b/tests/baselines/reference/recursiveReturns.js @@ -23,6 +23,7 @@ function R1() { function R2() { R2(); } function R3(n) { if (n == 0) { + //return; } else { R3(n--); diff --git a/tests/baselines/reference/sourceMap-SkippedNode.js b/tests/baselines/reference/sourceMap-SkippedNode.js index 656b5a244e9..daac27cf49f 100644 --- a/tests/baselines/reference/sourceMap-SkippedNode.js +++ b/tests/baselines/reference/sourceMap-SkippedNode.js @@ -7,7 +7,9 @@ try { //// [sourceMap-SkippedNode.js] try { +// ... } finally { +// N.B. No 'catch' block } //# sourceMappingURL=sourceMap-SkippedNode.js.map \ No newline at end of file diff --git a/tests/baselines/reference/sourceMap-SkippedNode.js.map b/tests/baselines/reference/sourceMap-SkippedNode.js.map index 77340424640..b86b3905a73 100644 --- a/tests/baselines/reference/sourceMap-SkippedNode.js.map +++ b/tests/baselines/reference/sourceMap-SkippedNode.js.map @@ -1,2 +1,2 @@ //// [sourceMap-SkippedNode.js.map] -{"version":3,"file":"sourceMap-SkippedNode.js","sourceRoot":"","sources":["sourceMap-SkippedNode.ts"],"names":[],"mappings":"AAAA,IAAI,CAAC;AAEL,CAAC;QAAS,CAAC;AAEX,CAAC"} \ No newline at end of file +{"version":3,"file":"sourceMap-SkippedNode.js","sourceRoot":"","sources":["sourceMap-SkippedNode.ts"],"names":[],"mappings":"AAAA,IAAI,CAAC;AACL,MAAM;AACN,CAAC;QAAS,CAAC;AACX,wBAAwB;AACxB,CAAC"} \ No newline at end of file diff --git a/tests/baselines/reference/sourceMap-SkippedNode.sourcemap.txt b/tests/baselines/reference/sourceMap-SkippedNode.sourcemap.txt index f68320a531f..b48a5f09f4a 100644 --- a/tests/baselines/reference/sourceMap-SkippedNode.sourcemap.txt +++ b/tests/baselines/reference/sourceMap-SkippedNode.sourcemap.txt @@ -12,6 +12,7 @@ sourceFile:sourceMap-SkippedNode.ts 1 > 2 >^^^^ 3 > ^ +4 > ^^-> 1 > 2 >try 3 > { @@ -19,34 +20,51 @@ sourceFile:sourceMap-SkippedNode.ts 2 >Emitted(1, 5) Source(1, 5) + SourceIndex(0) 3 >Emitted(1, 6) Source(1, 6) + SourceIndex(0) --- +>>>// ... +1-> +2 >^^^^^^ +1-> + > +2 >// ... +1->Emitted(2, 1) Source(2, 1) + SourceIndex(0) +2 >Emitted(2, 7) Source(2, 7) + SourceIndex(0) +--- >>>} 1 > 2 >^ 3 > ^^^^^^^^^-> 1 > - >// ... > 2 >} -1 >Emitted(2, 1) Source(3, 1) + SourceIndex(0) -2 >Emitted(2, 2) Source(3, 2) + SourceIndex(0) +1 >Emitted(3, 1) Source(3, 1) + SourceIndex(0) +2 >Emitted(3, 2) Source(3, 2) + SourceIndex(0) --- >>>finally { 1->^^^^^^^^ 2 > ^ +3 > ^^^^^^^^^^^^^^^^-> 1-> finally 2 > { -1->Emitted(3, 9) Source(3, 11) + SourceIndex(0) -2 >Emitted(3, 10) Source(3, 12) + SourceIndex(0) +1->Emitted(4, 9) Source(3, 11) + SourceIndex(0) +2 >Emitted(4, 10) Source(3, 12) + SourceIndex(0) +--- +>>>// N.B. No 'catch' block +1-> +2 >^^^^^^^^^^^^^^^^^^^^^^^^ +1-> + > +2 >// N.B. No 'catch' block +1->Emitted(5, 1) Source(4, 1) + SourceIndex(0) +2 >Emitted(5, 25) Source(4, 25) + SourceIndex(0) --- >>>} 1 > 2 >^ 3 > ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-> 1 > - >// N.B. No 'catch' block > 2 >} -1 >Emitted(4, 1) Source(5, 1) + SourceIndex(0) -2 >Emitted(4, 2) Source(5, 2) + SourceIndex(0) +1 >Emitted(6, 1) Source(5, 1) + SourceIndex(0) +2 >Emitted(6, 2) Source(5, 2) + SourceIndex(0) --- >>>//# sourceMappingURL=sourceMap-SkippedNode.js.map \ No newline at end of file diff --git a/tests/cases/compiler/commentLeadingCloseBrace.ts b/tests/cases/compiler/commentLeadingCloseBrace.ts new file mode 100644 index 00000000000..bdf7a604a9b --- /dev/null +++ b/tests/cases/compiler/commentLeadingCloseBrace.ts @@ -0,0 +1,11 @@ +declare function commentedParameters(...args): any; + +function ifelse() { + if (commentedParameters(1, 2)) { + /*comment1*/ + commentedParameters(3, 4); + /*comment2*/ + } else { + commentedParameters(5, 6); + } +} \ No newline at end of file From 915ffab8cc2224ebd7e0c8096fa979fb168de2f5 Mon Sep 17 00:00:00 2001 From: Vladimir Matveev Date: Tue, 7 Feb 2017 14:47:07 -0800 Subject: [PATCH 47/58] disable fs watcher for UNC paths on Windows (#13937) --- src/compiler/sys.ts | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/compiler/sys.ts b/src/compiler/sys.ts index 71ff4485343..8ac797507b1 100644 --- a/src/compiler/sys.ts +++ b/src/compiler/sys.ts @@ -485,7 +485,10 @@ namespace ts { // Node 4.0 `fs.watch` function supports the "recursive" option on both OSX and Windows // (ref: https://github.com/nodejs/node/pull/2649 and https://github.com/Microsoft/TypeScript/issues/4643) let options: any; - if (!directoryExists(directoryName)) { + if (!directoryExists(directoryName) || (isUNCPath(directoryName) && process.platform === "win32")) { + // do nothing if either + // - target folder does not exist + // - this is UNC path on Windows (https://github.com/Microsoft/TypeScript/issues/13874) return noOpFileWatcher; } @@ -509,6 +512,10 @@ namespace ts { }; } ); + + function isUNCPath(s: string): boolean { + return s.length > 2 && s.charCodeAt(0) === CharacterCodes.slash && s.charCodeAt(1) === CharacterCodes.slash; + } }, resolvePath: function(path: string): string { return _path.resolve(path); From 0a1d75dbd1718216ef7bf2606bea2b54955cd1bf Mon Sep 17 00:00:00 2001 From: Vladimir Matveev Date: Tue, 7 Feb 2017 18:14:23 -0800 Subject: [PATCH 48/58] use tsconfig.json files in jake (#13869) --- Jakefile.js | 201 +++++++++------------------------------------------- 1 file changed, 32 insertions(+), 169 deletions(-) diff --git a/Jakefile.js b/Jakefile.js index 0b3a26dbb77..f422a995725 100644 --- a/Jakefile.js +++ b/Jakefile.js @@ -6,6 +6,8 @@ var path = require("path"); var child_process = require("child_process"); var fold = require("travis-fold"); var runTestsInParallel = require("./scripts/mocha-parallel").runTestsInParallel; +var ts = require("./lib/typescript"); + // Variables var compilerDirectory = "src/compiler/"; @@ -34,6 +36,25 @@ if (process.env.path !== undefined) { process.env.PATH = nodeModulesPathPrefix + process.env.PATH; } +function filesFromConfig(configPath) { + console.log(configPath); + var configText = fs.readFileSync(configPath).toString(); + var config = ts.parseConfigFileTextToJson(configPath, configText, /*stripComments*/ true); + if (config.error) { + throw new Error(diagnosticsToString([config.error])); + } + const configFileContent = ts.parseJsonConfigFileContent(config.config, ts.sys, path.dirname(configPath)); + if (configFileContent.errors && configFileContent.errors.length) { + throw new Error(diagnosticsToString(configFileContent.errors)); + } + + return configFileContent.fileNames; + + function diagnosticsToString(s) { + return s.map(function(e) { return ts.flattenDiagnosticMessageText(e.messageText, ts.sys.newLine); }).join(ts.sys.newLine); + } +} + function toNs(diff) { return diff[0] * 1e9 + diff[1]; } @@ -56,173 +77,12 @@ function measure(marker) { console.log("travis_time:end:" + marker.id + ":start=" + toNs(marker.stamp) + ",finish=" + toNs(total) + ",duration=" + toNs(diff) + "\r"); } -var compilerSources = [ - "core.ts", - "performance.ts", - "sys.ts", - "types.ts", - "scanner.ts", - "parser.ts", - "utilities.ts", - "binder.ts", - "checker.ts", - "factory.ts", - "visitor.ts", - "transformers/destructuring.ts", - "transformers/ts.ts", - "transformers/jsx.ts", - "transformers/esnext.ts", - "transformers/es2017.ts", - "transformers/es2016.ts", - "transformers/es2015.ts", - "transformers/generators.ts", - "transformers/es5.ts", - "transformers/module/es2015.ts", - "transformers/module/system.ts", - "transformers/module/module.ts", - "transformer.ts", - "sourcemap.ts", - "comments.ts", - "declarationEmitter.ts", - "emitter.ts", - "program.ts", - "commandLineParser.ts", - "tsc.ts", - "diagnosticInformationMap.generated.ts" -].map(function (f) { - return path.join(compilerDirectory, f); -}); - -var servicesSources = [ - "core.ts", - "performance.ts", - "sys.ts", - "types.ts", - "scanner.ts", - "parser.ts", - "utilities.ts", - "binder.ts", - "checker.ts", - "factory.ts", - "visitor.ts", - "transformers/destructuring.ts", - "transformers/ts.ts", - "transformers/jsx.ts", - "transformers/esnext.ts", - "transformers/es2017.ts", - "transformers/es2016.ts", - "transformers/es2015.ts", - "transformers/generators.ts", - "transformers/es5.ts", - "transformers/module/es2015.ts", - "transformers/module/system.ts", - "transformers/module/module.ts", - "transformer.ts", - "sourcemap.ts", - "comments.ts", - "declarationEmitter.ts", - "emitter.ts", - "program.ts", - "commandLineParser.ts", - "diagnosticInformationMap.generated.ts" -].map(function (f) { - return path.join(compilerDirectory, f); -}).concat([ - "types.ts", - "utilities.ts", - "breakpoints.ts", - "classifier.ts", - "completions.ts", - "documentHighlights.ts", - "documentRegistry.ts", - "findAllReferences.ts", - "goToDefinition.ts", - "goToImplementation.ts", - "jsDoc.ts", - "jsTyping.ts", - "navigateTo.ts", - "navigationBar.ts", - "outliningElementsCollector.ts", - "patternMatcher.ts", - "preProcess.ts", - "rename.ts", - "services.ts", - "shims.ts", - "signatureHelp.ts", - "symbolDisplay.ts", - "transpile.ts", - // Formatting - "formatting/formatting.ts", - "formatting/formattingContext.ts", - "formatting/formattingRequestKind.ts", - "formatting/formattingScanner.ts", - "formatting/references.ts", - "formatting/rule.ts", - "formatting/ruleAction.ts", - "formatting/ruleDescriptor.ts", - "formatting/ruleFlag.ts", - "formatting/ruleOperation.ts", - "formatting/ruleOperationContext.ts", - "formatting/rules.ts", - "formatting/rulesMap.ts", - "formatting/rulesProvider.ts", - "formatting/smartIndenter.ts", - "formatting/tokenRange.ts", - // CodeFixes - "codeFixProvider.ts", - "codefixes/fixes.ts", - "codefixes/fixExtendsInterfaceBecomesImplements.ts", - "codefixes/fixClassIncorrectlyImplementsInterface.ts", - "codefixes/fixClassDoesntImplementInheritedAbstractMember.ts", - "codefixes/fixClassSuperMustPrecedeThisAccess.ts", - "codefixes/fixConstructorForDerivedNeedSuperCall.ts", - "codefixes/helpers.ts", - "codefixes/importFixes.ts", - "codefixes/unusedIdentifierFixes.ts" -].map(function (f) { - return path.join(servicesDirectory, f); -})); - -var baseServerCoreSources = [ - "builder.ts", - "editorServices.ts", - "lsHost.ts", - "project.ts", - "protocol.ts", - "scriptInfo.ts", - "scriptVersionCache.ts", - "session.ts", - "shared.ts", - "types.ts", - "typingsCache.ts", - "utilities.ts", -].map(function (f) { - return path.join(serverDirectory, f); -}); - -var serverCoreSources = [ - "server.ts" -].map(function (f) { - return path.join(serverDirectory, f); -}).concat(baseServerCoreSources); - -var cancellationTokenSources = [ - "cancellationToken.ts" -].map(function (f) { - return path.join(cancellationTokenDirectory, f); -}); - -var typingsInstallerSources = [ - "../types.ts", - "../shared.ts", - "typingsInstaller.ts", - "nodeTypingsInstaller.ts" -].map(function (f) { - return path.join(typingsInstallerDirectory, f); -}); - -var serverSources = serverCoreSources.concat(servicesSources); -var languageServiceLibrarySources = baseServerCoreSources.concat(servicesSources); +var compilerSources = filesFromConfig("./src/compiler/tsconfig.json"); +var servicesSources = filesFromConfig("./src/services/tsconfig.json"); +var cancellationTokenSources = filesFromConfig(path.join(serverDirectory, "cancellationToken/tsconfig.json")); +var typingsInstallerSources = filesFromConfig(path.join(serverDirectory, "typingsInstaller/tsconfig.json")); +var serverSources = filesFromConfig(path.join(serverDirectory, "tsconfig.json")) +var languageServiceLibrarySources = filesFromConfig(path.join(serverDirectory, "tsconfig.library.json")); var harnessCoreSources = [ "harness.ts", @@ -1230,13 +1090,16 @@ var lintTargets = compilerSources .concat(harnessSources) // Other harness sources .concat(["instrumenter.ts"].map(function (f) { return path.join(harnessDirectory, f) })) - .concat(serverCoreSources) + .concat(serverSources) .concat(tslintRulesFiles) .concat(servicesSources) .concat(typingsInstallerSources) .concat(cancellationTokenSources) .concat(["Gulpfile.ts"]) - .concat([nodeServerInFile, perftscPath, "tests/perfsys.ts", webhostPath]); + .concat([nodeServerInFile, perftscPath, "tests/perfsys.ts", webhostPath]) + .map(function (p) { return path.resolve(p) }); +// keep only unique items +lintTargets = Array.from(new Set(lintTargets)); function sendNextFile(files, child, callback, failures) { var file = files.pop(); From f4080a4f9e310fbbe24e5d2813bfebc1c362b85b Mon Sep 17 00:00:00 2001 From: Mohamed Hegazy Date: Tue, 7 Feb 2017 18:23:22 -0800 Subject: [PATCH 49/58] Add test for #13925 --- .../reference/capturedLetConstInLoop13.js | 52 ++++++++++++++++ .../capturedLetConstInLoop13.symbols | 48 +++++++++++++++ .../reference/capturedLetConstInLoop13.types | 59 +++++++++++++++++++ .../compiler/capturedLetConstInLoop13.ts | 22 +++++++ 4 files changed, 181 insertions(+) create mode 100644 tests/baselines/reference/capturedLetConstInLoop13.js create mode 100644 tests/baselines/reference/capturedLetConstInLoop13.symbols create mode 100644 tests/baselines/reference/capturedLetConstInLoop13.types create mode 100644 tests/cases/compiler/capturedLetConstInLoop13.ts diff --git a/tests/baselines/reference/capturedLetConstInLoop13.js b/tests/baselines/reference/capturedLetConstInLoop13.js new file mode 100644 index 00000000000..a2e0921ab1d --- /dev/null +++ b/tests/baselines/reference/capturedLetConstInLoop13.js @@ -0,0 +1,52 @@ +//// [capturedLetConstInLoop13.ts] +class Main { + + constructor() { + this.register("a", "b", "c"); + } + + private register(...names: string[]): void { + for (let name of names) { + + this.bar({ + [name + ".a"]: () => { this.foo(name); }, + }); + } + } + + private bar(a: any): void { } + + private foo(name: string): void { } + +} + +new Main(); + +//// [capturedLetConstInLoop13.js] +var Main = (function () { + function Main() { + this.register("a", "b", "c"); + } + Main.prototype.register = function () { + var _this = this; + var names = []; + for (var _i = 0; _i < arguments.length; _i++) { + names[_i] = arguments[_i]; + } + var _loop_1 = function (name) { + this_1.bar((_a = {}, + _a[name + ".a"] = function () { _this.foo(name); }, + _a)); + var _a; + }; + var this_1 = this; + for (var _a = 0, names_1 = names; _a < names_1.length; _a++) { + var name = names_1[_a]; + _loop_1(name); + } + }; + Main.prototype.bar = function (a) { }; + Main.prototype.foo = function (name) { }; + return Main; +}()); +new Main(); diff --git a/tests/baselines/reference/capturedLetConstInLoop13.symbols b/tests/baselines/reference/capturedLetConstInLoop13.symbols new file mode 100644 index 00000000000..c7a824d26fa --- /dev/null +++ b/tests/baselines/reference/capturedLetConstInLoop13.symbols @@ -0,0 +1,48 @@ +=== tests/cases/compiler/capturedLetConstInLoop13.ts === +class Main { +>Main : Symbol(Main, Decl(capturedLetConstInLoop13.ts, 0, 0)) + + constructor() { + this.register("a", "b", "c"); +>this.register : Symbol(Main.register, Decl(capturedLetConstInLoop13.ts, 4, 5)) +>this : Symbol(Main, Decl(capturedLetConstInLoop13.ts, 0, 0)) +>register : Symbol(Main.register, Decl(capturedLetConstInLoop13.ts, 4, 5)) + } + + private register(...names: string[]): void { +>register : Symbol(Main.register, Decl(capturedLetConstInLoop13.ts, 4, 5)) +>names : Symbol(names, Decl(capturedLetConstInLoop13.ts, 6, 21)) + + for (let name of names) { +>name : Symbol(name, Decl(capturedLetConstInLoop13.ts, 7, 16)) +>names : Symbol(names, Decl(capturedLetConstInLoop13.ts, 6, 21)) + + this.bar({ +>this.bar : Symbol(Main.bar, Decl(capturedLetConstInLoop13.ts, 13, 5)) +>this : Symbol(Main, Decl(capturedLetConstInLoop13.ts, 0, 0)) +>bar : Symbol(Main.bar, Decl(capturedLetConstInLoop13.ts, 13, 5)) + + [name + ".a"]: () => { this.foo(name); }, +>name : Symbol(name, Decl(capturedLetConstInLoop13.ts, 7, 16)) +>this.foo : Symbol(Main.foo, Decl(capturedLetConstInLoop13.ts, 15, 33)) +>this : Symbol(Main, Decl(capturedLetConstInLoop13.ts, 0, 0)) +>foo : Symbol(Main.foo, Decl(capturedLetConstInLoop13.ts, 15, 33)) +>name : Symbol(name, Decl(capturedLetConstInLoop13.ts, 7, 16)) + + }); + } + } + + private bar(a: any): void { } +>bar : Symbol(Main.bar, Decl(capturedLetConstInLoop13.ts, 13, 5)) +>a : Symbol(a, Decl(capturedLetConstInLoop13.ts, 15, 16)) + + private foo(name: string): void { } +>foo : Symbol(Main.foo, Decl(capturedLetConstInLoop13.ts, 15, 33)) +>name : Symbol(name, Decl(capturedLetConstInLoop13.ts, 17, 16)) + +} + +new Main(); +>Main : Symbol(Main, Decl(capturedLetConstInLoop13.ts, 0, 0)) + diff --git a/tests/baselines/reference/capturedLetConstInLoop13.types b/tests/baselines/reference/capturedLetConstInLoop13.types new file mode 100644 index 00000000000..e6f97255d75 --- /dev/null +++ b/tests/baselines/reference/capturedLetConstInLoop13.types @@ -0,0 +1,59 @@ +=== tests/cases/compiler/capturedLetConstInLoop13.ts === +class Main { +>Main : Main + + constructor() { + this.register("a", "b", "c"); +>this.register("a", "b", "c") : void +>this.register : (...names: string[]) => void +>this : this +>register : (...names: string[]) => void +>"a" : "a" +>"b" : "b" +>"c" : "c" + } + + private register(...names: string[]): void { +>register : (...names: string[]) => void +>names : string[] + + for (let name of names) { +>name : string +>names : string[] + + this.bar({ +>this.bar({ [name + ".a"]: () => { this.foo(name); }, }) : void +>this.bar : (a: any) => void +>this : this +>bar : (a: any) => void +>{ [name + ".a"]: () => { this.foo(name); }, } : { [x: string]: () => void; } + + [name + ".a"]: () => { this.foo(name); }, +>name + ".a" : string +>name : string +>".a" : ".a" +>() => { this.foo(name); } : () => void +>this.foo(name) : void +>this.foo : (name: string) => void +>this : this +>foo : (name: string) => void +>name : string + + }); + } + } + + private bar(a: any): void { } +>bar : (a: any) => void +>a : any + + private foo(name: string): void { } +>foo : (name: string) => void +>name : string + +} + +new Main(); +>new Main() : Main +>Main : typeof Main + diff --git a/tests/cases/compiler/capturedLetConstInLoop13.ts b/tests/cases/compiler/capturedLetConstInLoop13.ts new file mode 100644 index 00000000000..0aa00b0e1a0 --- /dev/null +++ b/tests/cases/compiler/capturedLetConstInLoop13.ts @@ -0,0 +1,22 @@ +class Main { + + constructor() { + this.register("a", "b", "c"); + } + + private register(...names: string[]): void { + for (let name of names) { + + this.bar({ + [name + ".a"]: () => { this.foo(name); }, + }); + } + } + + private bar(a: any): void { } + + private foo(name: string): void { } + +} + +new Main(); \ No newline at end of file From f4583313d9bf6ff3ed1e5464277c73f5bd124234 Mon Sep 17 00:00:00 2001 From: Andy Hanson Date: Wed, 8 Feb 2017 06:13:32 -0800 Subject: [PATCH 50/58] Use `!!` to convert to boolean --- src/harness/fourslash.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/harness/fourslash.ts b/src/harness/fourslash.ts index 3deddf1f2cc..c7f455bd753 100644 --- a/src/harness/fourslash.ts +++ b/src/harness/fourslash.ts @@ -911,7 +911,7 @@ namespace FourSlash { function rangeToReferenceEntry(r: Range) { let { isWriteAccess, isDefinition } = (r.marker && r.marker.data) || { isWriteAccess: false, isDefinition: false }; - isWriteAccess = isWriteAccess || false; isDefinition = isDefinition || false; + isWriteAccess = !!isWriteAccess; isDefinition = !!isDefinition; return { fileName: r.fileName, textSpan: { start: r.start, length: r.end - r.start }, isWriteAccess, isDefinition } } } From a928ad3bd36e8aea806b307ff0b4b2d683f12ee8 Mon Sep 17 00:00:00 2001 From: Kanchalai Tanglertsampan Date: Wed, 8 Feb 2017 10:17:58 -0800 Subject: [PATCH 51/58] Address code review: move only expose emitLeadingCommentsOfPosition --- src/compiler/comments.ts | 16 ++++++++++------ src/compiler/emitter.ts | 17 +++++++---------- 2 files changed, 17 insertions(+), 16 deletions(-) diff --git a/src/compiler/comments.ts b/src/compiler/comments.ts index 8e17bf2d91b..dcb471dcfcc 100644 --- a/src/compiler/comments.ts +++ b/src/compiler/comments.ts @@ -9,7 +9,7 @@ namespace ts { emitNodeWithComments(hint: EmitHint, node: Node, emitCallback: (hint: EmitHint, node: Node) => void): void; emitBodyWithDetachedComments(node: Node, detachedRange: TextRange, emitCallback: (node: Node) => void): void; emitTrailingCommentsOfPosition(pos: number): void; - emitLeadingComments(pos: number, isEmittedNode: boolean): void; + emitLeadingCommentsOfPosition(pos: number): void; } export function createCommentWriter(printerOptions: PrinterOptions, emitPos: ((pos: number) => void) | undefined): CommentWriter { @@ -33,7 +33,7 @@ namespace ts { emitNodeWithComments, emitBodyWithDetachedComments, emitTrailingCommentsOfPosition, - emitLeadingComments, + emitLeadingCommentsOfPosition, }; function emitNodeWithComments(hint: EmitHint, node: Node, emitCallback: (hint: EmitHint, node: Node) => void) { @@ -169,10 +169,6 @@ namespace ts { } function emitLeadingComments(pos: number, isEmittedNode: boolean) { - if (disabled) { - return; - } - hasWrittenComment = false; if (isEmittedNode) { @@ -216,6 +212,14 @@ namespace ts { } } + function emitLeadingCommentsOfPosition(pos: number) { + if (disabled || pos === -1) { + return; + } + + emitLeadingComments(pos, /*isEmittedNode*/ true); + } + function emitTrailingComments(pos: number) { forEachTrailingCommentToEmit(pos, emitTrailingComment); } diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index 7adac106e8c..fcb3fb826c9 100644 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -1,4 +1,4 @@ -/// +/// /// /// /// @@ -211,7 +211,7 @@ namespace ts { emitNodeWithComments, emitBodyWithDetachedComments, emitTrailingCommentsOfPosition, - emitLeadingComments, + emitLeadingCommentsOfPosition, } = comments; let currentSourceFile: SourceFile; @@ -1348,7 +1348,7 @@ namespace ts { writeToken(SyntaxKind.OpenBraceToken, node.pos, /*contextNode*/ node); emitBlockStatements(node); // We have to call emitLeadingComments explicitly here because otherwise leading comments of the close brace token will not be emitted - emitLeadingComments(node.statements.end, /*isEmittedNode*/true); + emitLeadingCommentsOfPosition(node.statements.end); writeToken(SyntaxKind.CloseBraceToken, node.statements.end, /*contextNode*/ node); } } @@ -2235,10 +2235,10 @@ namespace ts { // function commentedParameters( // /* Parameter a */ // a - // /* End of parameter a */ -> this comment doesn't consider to be trailing comment of parameter "a" due to newline + // /* End of parameter a */ -> this comment isn't considered to be trailing comment of parameter "a" due to newline // , - if (emitLeadingComments && delimiter && previousSibling.end !== parentNode.end) { - emitLeadingComments(previousSibling.end, /*isEmittedNode*/ previousSibling.kind !== SyntaxKind.NotEmittedStatement); + if (emitLeadingCommentsOfPosition && delimiter && previousSibling.end !== parentNode.end) { + emitLeadingCommentsOfPosition(previousSibling.end); } write(delimiter); @@ -2294,10 +2294,7 @@ namespace ts { // /* end of element 2 */ // ]; if (previousSibling && delimiter && previousSibling.end !== parentNode.end) { - emitLeadingComments(previousSibling.end, /*isEmittedNode*/ previousSibling.kind !== SyntaxKind.NotEmittedStatement); - if (hasTrailingComma) { - emitLeadingComments(previousSibling.end, /*isEmittedNode*/ previousSibling.kind !== SyntaxKind.NotEmittedStatement); - } + emitLeadingCommentsOfPosition(previousSibling.end); } // Decrease the indent, if requested. From bb71dcdde8bf95611cfe98d8b33738250f4fb5b8 Mon Sep 17 00:00:00 2001 From: Vladimir Matveev Date: Wed, 8 Feb 2017 11:01:32 -0800 Subject: [PATCH 52/58] add projectUsesOutFile field to protocol.CompileOnSaveAffectedFileListSingleProject (#13915) --- .../unittests/tsserverProjectSystem.ts | 48 +++++++++++++++++++ src/server/protocol.ts | 5 ++ src/server/session.ts | 3 +- 3 files changed, 55 insertions(+), 1 deletion(-) diff --git a/src/harness/unittests/tsserverProjectSystem.ts b/src/harness/unittests/tsserverProjectSystem.ts index 5ed0d981511..93027675bd6 100644 --- a/src/harness/unittests/tsserverProjectSystem.ts +++ b/src/harness/unittests/tsserverProjectSystem.ts @@ -3031,6 +3031,54 @@ namespace ts.projectSystem { }); }); + describe("emit with outFile or out setting", () => { + function test(opts: CompilerOptions, expectedUsesOutFile: boolean) { + const f1 = { + path: "/a/a.ts", + content: "let x = 1" + }; + const f2 = { + path: "/a/b.ts", + content: "let y = 1" + }; + const config = { + path: "/a/tsconfig.json", + content: JSON.stringify({ + compilerOptions: opts, + compileOnSave: true + }) + }; + const host = createServerHost([f1, f2, config]); + const session = createSession(host); + session.executeCommand({ + seq: 1, + type: "request", + command: "open", + arguments: { file: f1.path } + }); + checkNumberOfProjects(session.getProjectService(), { configuredProjects: 1 }); + const { response } = session.executeCommand({ + seq: 2, + type: "request", + command: "compileOnSaveAffectedFileList", + arguments: { file: f1.path } + }); + assert.equal((response).length, 1, "expected output for 1 project"); + assert.equal((response)[0].fileNames.length, 2, "expected output for 1 project"); + assert.equal((response)[0].projectUsesOutFile, expectedUsesOutFile, "usesOutFile"); + } + + it ("projectUsesOutFile should not be returned if not set", () => { + test({}, /*expectedUsesOutFile*/ false); + }); + it ("projectUsesOutFile should be true if outFile is set", () => { + test({ outFile: "/a/out.js" }, /*expectedUsesOutFile*/ true); + }); + it ("projectUsesOutFile should be true if out is set", () => { + test({ out: "/a/out.js" }, /*expectedUsesOutFile*/ true); + }); + }); + describe("import helpers", () => { it("should not crash in tsserver", () => { const f1 = { diff --git a/src/server/protocol.ts b/src/server/protocol.ts index e3fe17362d7..c1b78e9dbaa 100644 --- a/src/server/protocol.ts +++ b/src/server/protocol.ts @@ -1239,6 +1239,11 @@ namespace ts.server.protocol { * List of files names that should be recompiled */ fileNames: string[]; + + /** + * true if project uses outFile or out compiler option + */ + projectUsesOutFile: boolean; } /** diff --git a/src/server/session.ts b/src/server/session.ts index 825ad8506d7..5d745fc7965 100644 --- a/src/server/session.ts +++ b/src/server/session.ts @@ -1040,7 +1040,8 @@ namespace ts.server { if (project.compileOnSaveEnabled && project.languageServiceEnabled) { result.push({ projectFileName: project.getProjectName(), - fileNames: project.getCompileOnSaveAffectedFileList(info) + fileNames: project.getCompileOnSaveAffectedFileList(info), + projectUsesOutFile: !!project.getCompilerOptions().outFile || !!project.getCompilerOptions().out }); } } From 125dd57a757612367bcf495ed3070bb932ae75ed Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Wed, 8 Feb 2017 13:28:23 -0800 Subject: [PATCH 53/58] Fix assigned type of assignment nested in literals Fixes #12946 --- src/compiler/checker.ts | 10 +++++- .../reference/assignmentNestedInLiterals.js | 13 +++++++ .../assignmentNestedInLiterals.symbols | 25 +++++++++++++ .../assignmentNestedInLiterals.types | 35 +++++++++++++++++++ .../compiler/assignmentNestedInLiterals.ts | 6 ++++ 5 files changed, 88 insertions(+), 1 deletion(-) create mode 100644 tests/baselines/reference/assignmentNestedInLiterals.js create mode 100644 tests/baselines/reference/assignmentNestedInLiterals.symbols create mode 100644 tests/baselines/reference/assignmentNestedInLiterals.types create mode 100644 tests/cases/compiler/assignmentNestedInLiterals.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 4423b574e31..428a4e6eeef 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -9469,11 +9469,19 @@ namespace ts { } function getAssignedTypeOfBinaryExpression(node: BinaryExpression): Type { - return node.parent.kind === SyntaxKind.ArrayLiteralExpression || node.parent.kind === SyntaxKind.PropertyAssignment ? + const isDestructuringDefaultAssignment = + node.parent.kind === SyntaxKind.ArrayLiteralExpression && isDestructuringAssignmentTarget(node.parent) || + node.parent.kind === SyntaxKind.PropertyAssignment && isDestructuringAssignmentTarget(node.parent.parent); + return isDestructuringDefaultAssignment ? getTypeWithDefault(getAssignedType(node), node.right) : getTypeOfExpression(node.right); } + function isDestructuringAssignmentTarget(parent: Node) { + return parent.parent.kind === SyntaxKind.BinaryExpression && (parent.parent as BinaryExpression).left === parent || + parent.parent.kind === SyntaxKind.ForOfStatement && (parent.parent as ForOfStatement).initializer === parent; + } + function getAssignedTypeOfArrayLiteralElement(node: ArrayLiteralExpression, element: Expression): Type { return getTypeOfDestructuredArrayElement(getAssignedType(node), indexOf(node.elements, element)); } diff --git a/tests/baselines/reference/assignmentNestedInLiterals.js b/tests/baselines/reference/assignmentNestedInLiterals.js new file mode 100644 index 00000000000..cd4bc6c6699 --- /dev/null +++ b/tests/baselines/reference/assignmentNestedInLiterals.js @@ -0,0 +1,13 @@ +//// [assignmentNestedInLiterals.ts] +var target, x, y; +target = [x = 1, y = x]; + +var aegis, a, b; +aegis = { x: a = 1, y: b = a }; + + +//// [assignmentNestedInLiterals.js] +var target, x, y; +target = [x = 1, y = x]; +var aegis, a, b; +aegis = { x: a = 1, y: b = a }; diff --git a/tests/baselines/reference/assignmentNestedInLiterals.symbols b/tests/baselines/reference/assignmentNestedInLiterals.symbols new file mode 100644 index 00000000000..90edd9ed04f --- /dev/null +++ b/tests/baselines/reference/assignmentNestedInLiterals.symbols @@ -0,0 +1,25 @@ +=== tests/cases/compiler/assignmentNestedInLiterals.ts === +var target, x, y; +>target : Symbol(target, Decl(assignmentNestedInLiterals.ts, 0, 3)) +>x : Symbol(x, Decl(assignmentNestedInLiterals.ts, 0, 11)) +>y : Symbol(y, Decl(assignmentNestedInLiterals.ts, 0, 14)) + +target = [x = 1, y = x]; +>target : Symbol(target, Decl(assignmentNestedInLiterals.ts, 0, 3)) +>x : Symbol(x, Decl(assignmentNestedInLiterals.ts, 0, 11)) +>y : Symbol(y, Decl(assignmentNestedInLiterals.ts, 0, 14)) +>x : Symbol(x, Decl(assignmentNestedInLiterals.ts, 0, 11)) + +var aegis, a, b; +>aegis : Symbol(aegis, Decl(assignmentNestedInLiterals.ts, 3, 3)) +>a : Symbol(a, Decl(assignmentNestedInLiterals.ts, 3, 10)) +>b : Symbol(b, Decl(assignmentNestedInLiterals.ts, 3, 13)) + +aegis = { x: a = 1, y: b = a }; +>aegis : Symbol(aegis, Decl(assignmentNestedInLiterals.ts, 3, 3)) +>x : Symbol(x, Decl(assignmentNestedInLiterals.ts, 4, 9)) +>a : Symbol(a, Decl(assignmentNestedInLiterals.ts, 3, 10)) +>y : Symbol(y, Decl(assignmentNestedInLiterals.ts, 4, 19)) +>b : Symbol(b, Decl(assignmentNestedInLiterals.ts, 3, 13)) +>a : Symbol(a, Decl(assignmentNestedInLiterals.ts, 3, 10)) + diff --git a/tests/baselines/reference/assignmentNestedInLiterals.types b/tests/baselines/reference/assignmentNestedInLiterals.types new file mode 100644 index 00000000000..8c4d5aadc7d --- /dev/null +++ b/tests/baselines/reference/assignmentNestedInLiterals.types @@ -0,0 +1,35 @@ +=== tests/cases/compiler/assignmentNestedInLiterals.ts === +var target, x, y; +>target : any +>x : any +>y : any + +target = [x = 1, y = x]; +>target = [x = 1, y = x] : number[] +>target : any +>[x = 1, y = x] : number[] +>x = 1 : 1 +>x : any +>1 : 1 +>y = x : number +>y : any +>x : number + +var aegis, a, b; +>aegis : any +>a : any +>b : any + +aegis = { x: a = 1, y: b = a }; +>aegis = { x: a = 1, y: b = a } : { x: number; y: number; } +>aegis : any +>{ x: a = 1, y: b = a } : { x: number; y: number; } +>x : number +>a = 1 : 1 +>a : any +>1 : 1 +>y : number +>b = a : number +>b : any +>a : number + diff --git a/tests/cases/compiler/assignmentNestedInLiterals.ts b/tests/cases/compiler/assignmentNestedInLiterals.ts new file mode 100644 index 00000000000..5b1f52cb450 --- /dev/null +++ b/tests/cases/compiler/assignmentNestedInLiterals.ts @@ -0,0 +1,6 @@ +// @noImplicitAny: true +var target, x, y; +target = [x = 1, y = x]; + +var aegis, a, b; +aegis = { x: a = 1, y: b = a }; From 8b8c490ff6b5cd89cee0d9049c733e6bbba1a719 Mon Sep 17 00:00:00 2001 From: Kanchalai Tanglertsampan Date: Wed, 8 Feb 2017 13:36:19 -0800 Subject: [PATCH 54/58] Address code review: fix indentation --- src/compiler/emitter.ts | 2 ++ .../reference/amdImportAsPrimaryExpression.js | 2 +- tests/baselines/reference/argsInScope.js | 2 +- .../reference/commentLeadingCloseBrace.js | 2 +- .../commonJSImportAsPrimaryExpression.js | 2 +- .../reference/duplicateLocalVariable1.js | 2 +- .../jsFileCompilationLetBeingRenamed.js | 2 +- .../narrowExceptionVariableInCatchClause.js | 2 +- tests/baselines/reference/noCatchBlock.js | 4 +-- tests/baselines/reference/noCatchBlock.js.map | 2 +- .../reference/noCatchBlock.sourcemap.txt | 28 +++++++++---------- tests/baselines/reference/objectRestForOf.js | 2 +- .../baselines/reference/parserRealSource14.js | 2 +- tests/baselines/reference/recursiveReturns.js | 2 +- .../reference/sourceMap-SkippedNode.js | 4 +-- .../reference/sourceMap-SkippedNode.js.map | 2 +- .../sourceMap-SkippedNode.sourcemap.txt | 28 +++++++++---------- 17 files changed, 46 insertions(+), 44 deletions(-) diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index fcb3fb826c9..03804dfeebe 100644 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -1348,7 +1348,9 @@ namespace ts { writeToken(SyntaxKind.OpenBraceToken, node.pos, /*contextNode*/ node); emitBlockStatements(node); // We have to call emitLeadingComments explicitly here because otherwise leading comments of the close brace token will not be emitted + increaseIndent(); emitLeadingCommentsOfPosition(node.statements.end); + decreaseIndent(); writeToken(SyntaxKind.CloseBraceToken, node.statements.end, /*contextNode*/ node); } } diff --git a/tests/baselines/reference/amdImportAsPrimaryExpression.js b/tests/baselines/reference/amdImportAsPrimaryExpression.js index 25f390c0b32..6ff3216fb58 100644 --- a/tests/baselines/reference/amdImportAsPrimaryExpression.js +++ b/tests/baselines/reference/amdImportAsPrimaryExpression.js @@ -26,6 +26,6 @@ define(["require", "exports"], function (require, exports) { define(["require", "exports", "./foo_0"], function (require, exports, foo) { "use strict"; if (foo.E1.A === 0) { - // Should cause runtime import - interesting optimization possibility, as gets inlined to 0. + // Should cause runtime import - interesting optimization possibility, as gets inlined to 0. } }); diff --git a/tests/baselines/reference/argsInScope.js b/tests/baselines/reference/argsInScope.js index 27405a47d87..a38bc778039 100644 --- a/tests/baselines/reference/argsInScope.js +++ b/tests/baselines/reference/argsInScope.js @@ -17,7 +17,7 @@ var C = (function () { } C.prototype.P = function (ii, j, k) { for (var i = 0; i < arguments.length; i++) { - // WScript.Echo("param: " + arguments[i]); + // WScript.Echo("param: " + arguments[i]); } }; return C; diff --git a/tests/baselines/reference/commentLeadingCloseBrace.js b/tests/baselines/reference/commentLeadingCloseBrace.js index 9fc696219e1..d5f5afbb884 100644 --- a/tests/baselines/reference/commentLeadingCloseBrace.js +++ b/tests/baselines/reference/commentLeadingCloseBrace.js @@ -16,7 +16,7 @@ function ifelse() { if (commentedParameters(1, 2)) { /*comment1*/ commentedParameters(3, 4); - /*comment2*/ + /*comment2*/ } else { commentedParameters(5, 6); diff --git a/tests/baselines/reference/commonJSImportAsPrimaryExpression.js b/tests/baselines/reference/commonJSImportAsPrimaryExpression.js index 1eb7b5ff214..0cbb7470dfc 100644 --- a/tests/baselines/reference/commonJSImportAsPrimaryExpression.js +++ b/tests/baselines/reference/commonJSImportAsPrimaryExpression.js @@ -27,5 +27,5 @@ exports.C1 = C1; "use strict"; var foo = require("./foo_0"); if (foo.C1.s1) { -// Should cause runtime import + // Should cause runtime import } diff --git a/tests/baselines/reference/duplicateLocalVariable1.js b/tests/baselines/reference/duplicateLocalVariable1.js index 432830d85b6..39848b3bb6a 100644 --- a/tests/baselines/reference/duplicateLocalVariable1.js +++ b/tests/baselines/reference/duplicateLocalVariable1.js @@ -391,7 +391,7 @@ var TestRunner = (function () { } } if (testResult === false) { - //console.log(e.message); + //console.log(e.message); } } if ((testcase.errorMessageRegEx !== undefined) && !exception) { diff --git a/tests/baselines/reference/jsFileCompilationLetBeingRenamed.js b/tests/baselines/reference/jsFileCompilationLetBeingRenamed.js index bb2aa10dc95..a87dad3c914 100644 --- a/tests/baselines/reference/jsFileCompilationLetBeingRenamed.js +++ b/tests/baselines/reference/jsFileCompilationLetBeingRenamed.js @@ -9,6 +9,6 @@ function foo(a) { //// [out.js] function foo(a) { for (var a_1 = 0; a_1 < 10; a_1++) { - // do something + // do something } } diff --git a/tests/baselines/reference/narrowExceptionVariableInCatchClause.js b/tests/baselines/reference/narrowExceptionVariableInCatchClause.js index 18344df5994..b7dbf717e34 100644 --- a/tests/baselines/reference/narrowExceptionVariableInCatchClause.js +++ b/tests/baselines/reference/narrowExceptionVariableInCatchClause.js @@ -27,7 +27,7 @@ function tryCatch() { //// [narrowExceptionVariableInCatchClause.js] function tryCatch() { try { - // do stuff... + // do stuff... } catch (err) { if (isFooError(err)) { diff --git a/tests/baselines/reference/noCatchBlock.js b/tests/baselines/reference/noCatchBlock.js index 158ac1257f3..ecc9c7f8c7e 100644 --- a/tests/baselines/reference/noCatchBlock.js +++ b/tests/baselines/reference/noCatchBlock.js @@ -8,9 +8,9 @@ try { //// [noCatchBlock.js] try { -// ... + // ... } finally { -// N.B. No 'catch' block + // N.B. No 'catch' block } //# sourceMappingURL=noCatchBlock.js.map \ No newline at end of file diff --git a/tests/baselines/reference/noCatchBlock.js.map b/tests/baselines/reference/noCatchBlock.js.map index ddac2894e0b..392ec588108 100644 --- a/tests/baselines/reference/noCatchBlock.js.map +++ b/tests/baselines/reference/noCatchBlock.js.map @@ -1,2 +1,2 @@ //// [noCatchBlock.js.map] -{"version":3,"file":"noCatchBlock.js","sourceRoot":"","sources":["noCatchBlock.ts"],"names":[],"mappings":"AACA,IAAI,CAAC;AACJ,MAAM;AACP,CAAC;QAAS,CAAC;AACV,wBAAwB;AACzB,CAAC"} \ No newline at end of file +{"version":3,"file":"noCatchBlock.js","sourceRoot":"","sources":["noCatchBlock.ts"],"names":[],"mappings":"AACA,IAAI,CAAC;IACJ,MAAM;AACP,CAAC;QAAS,CAAC;IACV,wBAAwB;AACzB,CAAC"} \ No newline at end of file diff --git a/tests/baselines/reference/noCatchBlock.sourcemap.txt b/tests/baselines/reference/noCatchBlock.sourcemap.txt index a75c119ca9f..5210f12d734 100644 --- a/tests/baselines/reference/noCatchBlock.sourcemap.txt +++ b/tests/baselines/reference/noCatchBlock.sourcemap.txt @@ -12,7 +12,7 @@ sourceFile:noCatchBlock.ts 1 > 2 >^^^^ 3 > ^ -4 > ^^-> +4 > ^^^^^^-> 1 > > 2 >try @@ -21,14 +21,14 @@ sourceFile:noCatchBlock.ts 2 >Emitted(1, 5) Source(2, 5) + SourceIndex(0) 3 >Emitted(1, 6) Source(2, 6) + SourceIndex(0) --- ->>>// ... -1-> -2 >^^^^^^ +>>> // ... +1->^^^^ +2 > ^^^^^^ 1-> > -2 >// ... -1->Emitted(2, 1) Source(3, 2) + SourceIndex(0) -2 >Emitted(2, 7) Source(3, 8) + SourceIndex(0) +2 > // ... +1->Emitted(2, 5) Source(3, 2) + SourceIndex(0) +2 >Emitted(2, 11) Source(3, 8) + SourceIndex(0) --- >>>} 1 > @@ -43,20 +43,20 @@ sourceFile:noCatchBlock.ts >>>finally { 1->^^^^^^^^ 2 > ^ -3 > ^^^^^^^^^^^^^^^^-> +3 > ^^^^^^^^^^^^^^^^^^^^-> 1-> finally 2 > { 1->Emitted(4, 9) Source(4, 11) + SourceIndex(0) 2 >Emitted(4, 10) Source(4, 12) + SourceIndex(0) --- ->>>// N.B. No 'catch' block -1-> -2 >^^^^^^^^^^^^^^^^^^^^^^^^ +>>> // N.B. No 'catch' block +1->^^^^ +2 > ^^^^^^^^^^^^^^^^^^^^^^^^ 1-> > -2 >// N.B. No 'catch' block -1->Emitted(5, 1) Source(5, 2) + SourceIndex(0) -2 >Emitted(5, 25) Source(5, 26) + SourceIndex(0) +2 > // N.B. No 'catch' block +1->Emitted(5, 5) Source(5, 2) + SourceIndex(0) +2 >Emitted(5, 29) Source(5, 26) + SourceIndex(0) --- >>>} 1 > diff --git a/tests/baselines/reference/objectRestForOf.js b/tests/baselines/reference/objectRestForOf.js index 5f0399b2df2..7ff72db06e5 100644 --- a/tests/baselines/reference/objectRestForOf.js +++ b/tests/baselines/reference/objectRestForOf.js @@ -37,5 +37,5 @@ for (let _b of array) { } for (const norest of array.map(a => (Object.assign({}, a, { x: 'a string' })))) { [norest.x, norest.y]; -// x is now a string. who knows why. + // x is now a string. who knows why. } diff --git a/tests/baselines/reference/parserRealSource14.js b/tests/baselines/reference/parserRealSource14.js index 4e4e23e81c3..635d122db04 100644 --- a/tests/baselines/reference/parserRealSource14.js +++ b/tests/baselines/reference/parserRealSource14.js @@ -1011,7 +1011,7 @@ var TypeScript; ctx.path.push(cur); } else { - //logger.log("TODO: Ignoring node because minChar, limChar not better than previous node in stack"); + //logger.log("TODO: Ignoring node because minChar, limChar not better than previous node in stack"); } } // The AST walker skips comments, but we might be in one, so check the pre/post comments for this node manually diff --git a/tests/baselines/reference/recursiveReturns.js b/tests/baselines/reference/recursiveReturns.js index 56762a9ad2d..d2619e18796 100644 --- a/tests/baselines/reference/recursiveReturns.js +++ b/tests/baselines/reference/recursiveReturns.js @@ -23,7 +23,7 @@ function R1() { function R2() { R2(); } function R3(n) { if (n == 0) { - //return; + //return; } else { R3(n--); diff --git a/tests/baselines/reference/sourceMap-SkippedNode.js b/tests/baselines/reference/sourceMap-SkippedNode.js index daac27cf49f..f25c0d75c82 100644 --- a/tests/baselines/reference/sourceMap-SkippedNode.js +++ b/tests/baselines/reference/sourceMap-SkippedNode.js @@ -7,9 +7,9 @@ try { //// [sourceMap-SkippedNode.js] try { -// ... + // ... } finally { -// N.B. No 'catch' block + // N.B. No 'catch' block } //# sourceMappingURL=sourceMap-SkippedNode.js.map \ No newline at end of file diff --git a/tests/baselines/reference/sourceMap-SkippedNode.js.map b/tests/baselines/reference/sourceMap-SkippedNode.js.map index b86b3905a73..f3444919d41 100644 --- a/tests/baselines/reference/sourceMap-SkippedNode.js.map +++ b/tests/baselines/reference/sourceMap-SkippedNode.js.map @@ -1,2 +1,2 @@ //// [sourceMap-SkippedNode.js.map] -{"version":3,"file":"sourceMap-SkippedNode.js","sourceRoot":"","sources":["sourceMap-SkippedNode.ts"],"names":[],"mappings":"AAAA,IAAI,CAAC;AACL,MAAM;AACN,CAAC;QAAS,CAAC;AACX,wBAAwB;AACxB,CAAC"} \ No newline at end of file +{"version":3,"file":"sourceMap-SkippedNode.js","sourceRoot":"","sources":["sourceMap-SkippedNode.ts"],"names":[],"mappings":"AAAA,IAAI,CAAC;IACL,MAAM;AACN,CAAC;QAAS,CAAC;IACX,wBAAwB;AACxB,CAAC"} \ No newline at end of file diff --git a/tests/baselines/reference/sourceMap-SkippedNode.sourcemap.txt b/tests/baselines/reference/sourceMap-SkippedNode.sourcemap.txt index b48a5f09f4a..c54676a697e 100644 --- a/tests/baselines/reference/sourceMap-SkippedNode.sourcemap.txt +++ b/tests/baselines/reference/sourceMap-SkippedNode.sourcemap.txt @@ -12,7 +12,7 @@ sourceFile:sourceMap-SkippedNode.ts 1 > 2 >^^^^ 3 > ^ -4 > ^^-> +4 > ^^^^^^-> 1 > 2 >try 3 > { @@ -20,14 +20,14 @@ sourceFile:sourceMap-SkippedNode.ts 2 >Emitted(1, 5) Source(1, 5) + SourceIndex(0) 3 >Emitted(1, 6) Source(1, 6) + SourceIndex(0) --- ->>>// ... -1-> -2 >^^^^^^ +>>> // ... +1->^^^^ +2 > ^^^^^^ 1-> > -2 >// ... -1->Emitted(2, 1) Source(2, 1) + SourceIndex(0) -2 >Emitted(2, 7) Source(2, 7) + SourceIndex(0) +2 > // ... +1->Emitted(2, 5) Source(2, 1) + SourceIndex(0) +2 >Emitted(2, 11) Source(2, 7) + SourceIndex(0) --- >>>} 1 > @@ -42,20 +42,20 @@ sourceFile:sourceMap-SkippedNode.ts >>>finally { 1->^^^^^^^^ 2 > ^ -3 > ^^^^^^^^^^^^^^^^-> +3 > ^^^^^^^^^^^^^^^^^^^^-> 1-> finally 2 > { 1->Emitted(4, 9) Source(3, 11) + SourceIndex(0) 2 >Emitted(4, 10) Source(3, 12) + SourceIndex(0) --- ->>>// N.B. No 'catch' block -1-> -2 >^^^^^^^^^^^^^^^^^^^^^^^^ +>>> // N.B. No 'catch' block +1->^^^^ +2 > ^^^^^^^^^^^^^^^^^^^^^^^^ 1-> > -2 >// N.B. No 'catch' block -1->Emitted(5, 1) Source(4, 1) + SourceIndex(0) -2 >Emitted(5, 25) Source(4, 25) + SourceIndex(0) +2 > // N.B. No 'catch' block +1->Emitted(5, 5) Source(4, 1) + SourceIndex(0) +2 >Emitted(5, 29) Source(4, 25) + SourceIndex(0) --- >>>} 1 > From a46cb033db7ad608c81e2541052cc1e3633ecadc Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Wed, 8 Feb 2017 16:14:36 -0800 Subject: [PATCH 55/58] Add for-of test case --- .../reference/assignmentNestedInLiterals.js | 8 ++++++++ .../reference/assignmentNestedInLiterals.symbols | 12 ++++++++++++ .../reference/assignmentNestedInLiterals.types | 16 ++++++++++++++++ .../cases/compiler/assignmentNestedInLiterals.ts | 4 ++++ 4 files changed, 40 insertions(+) diff --git a/tests/baselines/reference/assignmentNestedInLiterals.js b/tests/baselines/reference/assignmentNestedInLiterals.js index cd4bc6c6699..8a048082565 100644 --- a/tests/baselines/reference/assignmentNestedInLiterals.js +++ b/tests/baselines/reference/assignmentNestedInLiterals.js @@ -4,6 +4,10 @@ target = [x = 1, y = x]; var aegis, a, b; aegis = { x: a = 1, y: b = a }; + +var kowloona, c, d; +for (kowloona of [c = 1, d = c]) { +} //// [assignmentNestedInLiterals.js] @@ -11,3 +15,7 @@ var target, x, y; target = [x = 1, y = x]; var aegis, a, b; aegis = { x: a = 1, y: b = a }; +var kowloona, c, d; +for (var _i = 0, _a = [c = 1, d = c]; _i < _a.length; _i++) { + kowloona = _a[_i]; +} diff --git a/tests/baselines/reference/assignmentNestedInLiterals.symbols b/tests/baselines/reference/assignmentNestedInLiterals.symbols index 90edd9ed04f..761930ab9ce 100644 --- a/tests/baselines/reference/assignmentNestedInLiterals.symbols +++ b/tests/baselines/reference/assignmentNestedInLiterals.symbols @@ -23,3 +23,15 @@ aegis = { x: a = 1, y: b = a }; >b : Symbol(b, Decl(assignmentNestedInLiterals.ts, 3, 13)) >a : Symbol(a, Decl(assignmentNestedInLiterals.ts, 3, 10)) +var kowloona, c, d; +>kowloona : Symbol(kowloona, Decl(assignmentNestedInLiterals.ts, 6, 3)) +>c : Symbol(c, Decl(assignmentNestedInLiterals.ts, 6, 13)) +>d : Symbol(d, Decl(assignmentNestedInLiterals.ts, 6, 16)) + +for (kowloona of [c = 1, d = c]) { +>kowloona : Symbol(kowloona, Decl(assignmentNestedInLiterals.ts, 6, 3)) +>c : Symbol(c, Decl(assignmentNestedInLiterals.ts, 6, 13)) +>d : Symbol(d, Decl(assignmentNestedInLiterals.ts, 6, 16)) +>c : Symbol(c, Decl(assignmentNestedInLiterals.ts, 6, 13)) +} + diff --git a/tests/baselines/reference/assignmentNestedInLiterals.types b/tests/baselines/reference/assignmentNestedInLiterals.types index 8c4d5aadc7d..8ab73f80691 100644 --- a/tests/baselines/reference/assignmentNestedInLiterals.types +++ b/tests/baselines/reference/assignmentNestedInLiterals.types @@ -33,3 +33,19 @@ aegis = { x: a = 1, y: b = a }; >b : any >a : number +var kowloona, c, d; +>kowloona : any +>c : any +>d : any + +for (kowloona of [c = 1, d = c]) { +>kowloona : any +>[c = 1, d = c] : number[] +>c = 1 : 1 +>c : any +>1 : 1 +>d = c : number +>d : any +>c : number +} + diff --git a/tests/cases/compiler/assignmentNestedInLiterals.ts b/tests/cases/compiler/assignmentNestedInLiterals.ts index 5b1f52cb450..09d8c94488f 100644 --- a/tests/cases/compiler/assignmentNestedInLiterals.ts +++ b/tests/cases/compiler/assignmentNestedInLiterals.ts @@ -4,3 +4,7 @@ target = [x = 1, y = x]; var aegis, a, b; aegis = { x: a = 1, y: b = a }; + +var kowloona, c, d; +for (kowloona of [c = 1, d = c]) { +} From 2480e8d492ecd90849b189f98e57eb63ad1918c3 Mon Sep 17 00:00:00 2001 From: Vladimir Matveev Date: Wed, 8 Feb 2017 20:35:01 -0800 Subject: [PATCH 56/58] do secondary lookup only if module has non-relative name --- Jakefile.js | 1 - src/harness/unittests/typingsInstaller.ts | 39 +++++++++++++++++++++++ src/server/lsHost.ts | 2 +- 3 files changed, 40 insertions(+), 2 deletions(-) diff --git a/Jakefile.js b/Jakefile.js index f422a995725..4fd3be57e4f 100644 --- a/Jakefile.js +++ b/Jakefile.js @@ -37,7 +37,6 @@ if (process.env.path !== undefined) { } function filesFromConfig(configPath) { - console.log(configPath); var configText = fs.readFileSync(configPath).toString(); var config = ts.parseConfigFileTextToJson(configPath, configText, /*stripComments*/ true); if (config.error) { diff --git a/src/harness/unittests/typingsInstaller.ts b/src/harness/unittests/typingsInstaller.ts index 2b79141c3e3..29076df80f2 100644 --- a/src/harness/unittests/typingsInstaller.ts +++ b/src/harness/unittests/typingsInstaller.ts @@ -46,6 +46,45 @@ namespace ts.projectSystem { import typingsName = server.typingsInstaller.typingsName; + describe("local module", () => { + it("should not be picked up", () => { + const f1 = { + path: "/a/app.js", + content: "const c = require('./config');" + }; + const f2 = { + path: "/a/config.js", + content: "export let x = 1" + }; + const typesCache = "/cache" + const typesConfig = { + path: typesCache + "/node_modules/@types/config/index.d.ts", + content: "export let y: number;" + }; + const config = { + path: "/a/jsconfig.json", + content: JSON.stringify({ + compilerOptions: { moduleResolution: "commonjs" }, + typeAcquisition: { enable: true } + }) + }; + const host = createServerHost([f1, f2, config, typesConfig]); + const installer = new (class extends Installer { + constructor() { + super(host, { typesRegistry: createTypesRegistry("config"), globalTypingsCacheLocation: typesCache }); + } + installWorker(_requestId: number, _args: string[], _cwd: string, _cb: server.typingsInstaller.RequestCompletedAction) { + assert(false, "should not be called") + } + })(); + const service = createProjectService(host, { typingsInstaller: installer }); + service.openClientFile(f1.path); + service.checkNumberOfProjects({ configuredProjects: 1 }); + checkProjectActualFiles(service.configuredProjects[0], [f1.path, f2.path]); + installer.installAll(0); + }); + }); + describe("typingsInstaller", () => { it("configured projects (typings installed) 1", () => { const file1 = { diff --git a/src/server/lsHost.ts b/src/server/lsHost.ts index 9d8c9c08cb6..eee80d82e7f 100644 --- a/src/server/lsHost.ts +++ b/src/server/lsHost.ts @@ -28,7 +28,7 @@ namespace ts.server { : undefined; const primaryResult = resolveModuleName(moduleName, containingFile, compilerOptions, host); // return result immediately only if it is .ts, .tsx or .d.ts - if (!(primaryResult.resolvedModule && extensionIsTypeScript(primaryResult.resolvedModule.extension)) && globalCache !== undefined) { + if (moduleHasNonRelativeName(moduleName) && !(primaryResult.resolvedModule && extensionIsTypeScript(primaryResult.resolvedModule.extension)) && globalCache !== undefined) { // otherwise try to load typings from @types // create different collection of failed lookup locations for second pass From 8da2bd97bd0389fffb62d852d6e8ddeda53df47c Mon Sep 17 00:00:00 2001 From: Kanchalai Tanglertsampan Date: Thu, 9 Feb 2017 12:32:50 -0800 Subject: [PATCH 57/58] Address code review --- src/compiler/emitter.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index 03804dfeebe..e881c94cc83 100644 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -2239,7 +2239,7 @@ namespace ts { // a // /* End of parameter a */ -> this comment isn't considered to be trailing comment of parameter "a" due to newline // , - if (emitLeadingCommentsOfPosition && delimiter && previousSibling.end !== parentNode.end) { + if (delimiter && previousSibling.end !== parentNode.end) { emitLeadingCommentsOfPosition(previousSibling.end); } write(delimiter); From 84fc29f9005f969f84480e3d142a88087d6b9f71 Mon Sep 17 00:00:00 2001 From: Mohamed Hegazy Date: Thu, 9 Feb 2017 12:46:09 -0800 Subject: [PATCH 58/58] Fix lint failures detected by tslint@4.4.2 --- src/compiler/sys.ts | 2 +- src/harness/fourslash.ts | 2 +- src/harness/harnessLanguageService.ts | 4 ++-- src/harness/unittests/tsserverProjectSystem.ts | 2 +- src/server/cancellationToken/cancellationToken.ts | 2 +- src/services/codefixes/unusedIdentifierFixes.ts | 4 ++-- 6 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/compiler/sys.ts b/src/compiler/sys.ts index 8ac797507b1..c90a3484a8a 100644 --- a/src/compiler/sys.ts +++ b/src/compiler/sys.ts @@ -486,7 +486,7 @@ namespace ts { // (ref: https://github.com/nodejs/node/pull/2649 and https://github.com/Microsoft/TypeScript/issues/4643) let options: any; if (!directoryExists(directoryName) || (isUNCPath(directoryName) && process.platform === "win32")) { - // do nothing if either + // do nothing if either // - target folder does not exist // - this is UNC path on Windows (https://github.com/Microsoft/TypeScript/issues/13874) return noOpFileWatcher; diff --git a/src/harness/fourslash.ts b/src/harness/fourslash.ts index c7f455bd753..fc85fb7276c 100644 --- a/src/harness/fourslash.ts +++ b/src/harness/fourslash.ts @@ -183,7 +183,7 @@ namespace FourSlash { // The current caret position in the active file public currentCaretPosition = 0; - public lastKnownMarker: string = ""; + public lastKnownMarker = ""; // The file that's currently 'opened' public activeFile: FourSlashFile; diff --git a/src/harness/harnessLanguageService.ts b/src/harness/harnessLanguageService.ts index cd44fbf7a3a..59930fd98ba 100644 --- a/src/harness/harnessLanguageService.ts +++ b/src/harness/harnessLanguageService.ts @@ -5,7 +5,7 @@ namespace Harness.LanguageService { export class ScriptInfo { - public version: number = 1; + public version = 1; public editRanges: { length: number; textChangeRange: ts.TextChangeRange; }[] = []; private lineMap: number[] = undefined; @@ -594,7 +594,7 @@ namespace Harness.LanguageService { class SessionServerHost implements ts.server.ServerHost, ts.server.Logger { args: string[] = []; newLine: string; - useCaseSensitiveFileNames: boolean = false; + useCaseSensitiveFileNames = false; constructor(private host: NativeLanguageServiceHost) { this.newLine = this.host.getNewLine(); diff --git a/src/harness/unittests/tsserverProjectSystem.ts b/src/harness/unittests/tsserverProjectSystem.ts index 93027675bd6..e6f4abde382 100644 --- a/src/harness/unittests/tsserverProjectSystem.ts +++ b/src/harness/unittests/tsserverProjectSystem.ts @@ -3115,7 +3115,7 @@ namespace ts.projectSystem { let options = project.getCompilerOptions(); assert.isTrue(options.maxNodeModuleJsDepth === 2); - // Assert the option sticks + // Assert the option sticks projectService.setCompilerOptionsForInferredProjects({ target: ScriptTarget.ES2016 }); project = projectService.inferredProjects[0]; options = project.getCompilerOptions(); diff --git a/src/server/cancellationToken/cancellationToken.ts b/src/server/cancellationToken/cancellationToken.ts index 6d3dec67cc6..de59f3a1bce 100644 --- a/src/server/cancellationToken/cancellationToken.ts +++ b/src/server/cancellationToken/cancellationToken.ts @@ -1,7 +1,7 @@ /// -// TODO: extract services types +// TODO: extract services types interface HostCancellationToken { isCancellationRequested(): boolean; } diff --git a/src/services/codefixes/unusedIdentifierFixes.ts b/src/services/codefixes/unusedIdentifierFixes.ts index 0ca01a81eb1..6c0bc04eca8 100644 --- a/src/services/codefixes/unusedIdentifierFixes.ts +++ b/src/services/codefixes/unusedIdentifierFixes.ts @@ -94,9 +94,9 @@ namespace ts.codefix { return removeSingleItem(namedImports.elements, token); } - // handle case where "import d, * as ns from './file'" + // handle case where "import d, * as ns from './file'" // or "'import {a, b as ns} from './file'" - case SyntaxKind.ImportClause: // this covers both 'import |d|' and 'import |d,| *' + case SyntaxKind.ImportClause: // this covers both 'import |d|' and 'import |d,| *' const importClause = token.parent; if (!importClause.namedBindings) { // |import d from './file'| or |import * as ns from './file'| const importDecl = findImportDeclaration(importClause);