diff --git a/.gitignore b/.gitignore index afd10c0786da9..c6f87d986b434 100644 --- a/.gitignore +++ b/.gitignore @@ -84,3 +84,4 @@ tests/cases/user/puppeteer/puppeteer tests/cases/user/axios-src/axios-src tests/cases/user/prettier/prettier .eslintcache +*v8.log \ No newline at end of file diff --git a/src/compiler/binder.ts b/src/compiler/binder.ts index 64fbdbce0e572..7ce19bc264fb8 100644 --- a/src/compiler/binder.ts +++ b/src/compiler/binder.ts @@ -21,6 +21,8 @@ import { BreakOrContinueStatement, CallChain, CallExpression, + canHaveLocals, + canHaveSymbol, CaseBlock, CaseClause, cast, @@ -104,8 +106,11 @@ import { getTextOfIdentifierOrLiteral, getThisContainer, getTokenPosOfNode, + HasContainerFlags, hasDynamicName, + HasFlowNode, hasJSDocNodes, + HasLocals, hasSyntacticModifier, Identifier, idText, @@ -126,9 +131,11 @@ import { isBindingPattern, isBlock, isBlockOrCatchScoped, + IsBlockScopedContainer, isCallExpression, isClassStaticBlockDeclaration, isConditionalTypeNode, + IsContainer, isDeclaration, isDeclarationStatement, isDestructuringAssignment, @@ -223,6 +230,7 @@ import { length, LiteralLikeElementAccessExpression, MappedTypeNode, + MetaProperty, MethodDeclaration, ModifierFlags, ModuleBlock, @@ -250,9 +258,11 @@ import { PrefixUnaryExpression, PrivateIdentifier, PropertyAccessChain, + PropertyAccessEntityNameExpression, PropertyAccessExpression, PropertyDeclaration, PropertySignature, + QualifiedName, removeFileExtension, ReturnStatement, ScriptTarget, @@ -270,6 +280,7 @@ import { SpreadElement, Statement, StringLiteral, + SuperExpression, SwitchStatement, Symbol, SymbolFlags, @@ -277,6 +288,7 @@ import { SymbolTable, SyntaxKind, TextRange, + ThisExpression, ThrowStatement, TokenFlags, tokenToString, @@ -486,10 +498,10 @@ function createBinder(): (file: SourceFile, options: CompilerOptions) => void { let options: CompilerOptions; let languageVersion: ScriptTarget; let parent: Node; - let container: Node; - let thisParentContainer: Node; // Container one level up - let blockScopeContainer: Node; - let lastContainer: Node; + let container: IsContainer | EntityNameExpression; + let thisParentContainer: IsContainer | EntityNameExpression; // Container one level up + let blockScopeContainer: IsBlockScopedContainer; + let lastContainer: HasLocals; let delayedTypeAliases: (JSDocTypedefTag | JSDocCallbackTag | JSDocEnumTag)[]; let seenThisKeyword: boolean; @@ -852,6 +864,7 @@ function createBinder(): (file: SourceFile, options: CompilerOptions) => void { return declareSymbol(container.symbol.exports!, container.symbol, node, symbolFlags, symbolExcludes); } else { + Debug.assertNode(container, canHaveLocals); return declareSymbol(container.locals!, /*parent*/ undefined, node, symbolFlags, symbolExcludes); } } @@ -873,7 +886,7 @@ function createBinder(): (file: SourceFile, options: CompilerOptions) => void { // and should never be merged directly with other augmentation, and the latter case would be possible if automatic merge is allowed. if (isJSDocTypeAlias(node)) Debug.assert(isInJSFile(node)); // We shouldn't add symbols for JSDoc nodes if not in a JS file. if (!isAmbientModule(node) && (hasExportModifier || container.flags & NodeFlags.ExportContext)) { - if (!container.locals || (hasSyntacticModifier(node, ModifierFlags.Default) && !getDeclarationName(node))) { + if (!canHaveLocals(container) || !container.locals || (hasSyntacticModifier(node, ModifierFlags.Default) && !getDeclarationName(node))) { return declareSymbol(container.symbol.exports!, container.symbol, node, symbolFlags, symbolExcludes); // No local symbol for an unnamed default! } const exportKind = symbolFlags & SymbolFlags.Value ? SymbolFlags.ExportValue : 0; @@ -883,6 +896,7 @@ function createBinder(): (file: SourceFile, options: CompilerOptions) => void { return local; } else { + Debug.assertNode(container, canHaveLocals); return declareSymbol(container.locals!, /*parent*/ undefined, node, symbolFlags, symbolExcludes); } } @@ -909,7 +923,7 @@ function createBinder(): (file: SourceFile, options: CompilerOptions) => void { // All container nodes are kept on a linked list in declaration order. This list is used by // the getLocalNameOfContainer function in the type checker to validate that the local name // used for a container is unique. - function bindContainer(node: Mutable, containerFlags: ContainerFlags) { + function bindContainer(node: Mutable, containerFlags: ContainerFlags) { // Before we recurse into a node's children, we first save the existing parent, container // and block-container. Then after we pop out of processing the children, we restore // these saved values. @@ -938,15 +952,17 @@ function createBinder(): (file: SourceFile, options: CompilerOptions) => void { if (node.kind !== SyntaxKind.ArrowFunction) { thisParentContainer = container; } - container = blockScopeContainer = node; + container = blockScopeContainer = node as IsContainer; if (containerFlags & ContainerFlags.HasLocals) { - container.locals = createSymbolTable(); + (container as HasLocals).locals = createSymbolTable(); + addToContainerChain(container as HasLocals); } - addToContainerChain(container); } else if (containerFlags & ContainerFlags.IsBlockScopedContainer) { - blockScopeContainer = node; - blockScopeContainer.locals = undefined; + blockScopeContainer = node as IsBlockScopedContainer; + if (containerFlags & ContainerFlags.HasLocals) { + (blockScopeContainer as HasLocals).locals = undefined; + } } if (containerFlags & ContainerFlags.IsControlFlowContainer) { const saveCurrentFlow = currentFlow; @@ -1051,7 +1067,7 @@ function createBinder(): (file: SourceFile, options: CompilerOptions) => void { return; } if (node.kind >= SyntaxKind.FirstStatement && node.kind <= SyntaxKind.LastStatement && !options.allowUnreachableCode) { - node.flowNode = currentFlow; + (node as HasFlowNode).flowNode = currentFlow; } switch (node.kind) { case SyntaxKind.WhileStatement: @@ -2121,88 +2137,7 @@ function createBinder(): (file: SourceFile, options: CompilerOptions) => void { } } - function getContainerFlags(node: Node): ContainerFlags { - switch (node.kind) { - case SyntaxKind.ClassExpression: - case SyntaxKind.ClassDeclaration: - case SyntaxKind.EnumDeclaration: - case SyntaxKind.ObjectLiteralExpression: - case SyntaxKind.TypeLiteral: - case SyntaxKind.JSDocTypeLiteral: - case SyntaxKind.JsxAttributes: - return ContainerFlags.IsContainer; - - case SyntaxKind.InterfaceDeclaration: - return ContainerFlags.IsContainer | ContainerFlags.IsInterface; - - case SyntaxKind.ModuleDeclaration: - case SyntaxKind.TypeAliasDeclaration: - case SyntaxKind.MappedType: - case SyntaxKind.IndexSignature: - return ContainerFlags.IsContainer | ContainerFlags.HasLocals; - - case SyntaxKind.SourceFile: - return ContainerFlags.IsContainer | ContainerFlags.IsControlFlowContainer | ContainerFlags.HasLocals; - - case SyntaxKind.GetAccessor: - case SyntaxKind.SetAccessor: - case SyntaxKind.MethodDeclaration: - if (isObjectLiteralOrClassExpressionMethodOrAccessor(node)) { - return ContainerFlags.IsContainer | ContainerFlags.IsControlFlowContainer | ContainerFlags.HasLocals | ContainerFlags.IsFunctionLike | ContainerFlags.IsObjectLiteralOrClassExpressionMethodOrAccessor; - } - // falls through - case SyntaxKind.Constructor: - case SyntaxKind.FunctionDeclaration: - case SyntaxKind.MethodSignature: - case SyntaxKind.CallSignature: - case SyntaxKind.JSDocSignature: - case SyntaxKind.JSDocFunctionType: - case SyntaxKind.FunctionType: - case SyntaxKind.ConstructSignature: - case SyntaxKind.ConstructorType: - case SyntaxKind.ClassStaticBlockDeclaration: - return ContainerFlags.IsContainer | ContainerFlags.IsControlFlowContainer | ContainerFlags.HasLocals | ContainerFlags.IsFunctionLike; - - case SyntaxKind.FunctionExpression: - case SyntaxKind.ArrowFunction: - return ContainerFlags.IsContainer | ContainerFlags.IsControlFlowContainer | ContainerFlags.HasLocals | ContainerFlags.IsFunctionLike | ContainerFlags.IsFunctionExpression; - - case SyntaxKind.ModuleBlock: - return ContainerFlags.IsControlFlowContainer; - case SyntaxKind.PropertyDeclaration: - return (node as PropertyDeclaration).initializer ? ContainerFlags.IsControlFlowContainer : 0; - - case SyntaxKind.CatchClause: - case SyntaxKind.ForStatement: - case SyntaxKind.ForInStatement: - case SyntaxKind.ForOfStatement: - case SyntaxKind.CaseBlock: - return ContainerFlags.IsBlockScopedContainer; - - case SyntaxKind.Block: - // do not treat blocks directly inside a function as a block-scoped-container. - // Locals that reside in this block should go to the function locals. Otherwise 'x' - // would not appear to be a redeclaration of a block scoped local in the following - // example: - // - // function foo() { - // var x; - // let x; - // } - // - // If we placed 'var x' into the function locals and 'let x' into the locals of - // the block, then there would be no collision. - // - // By not creating a new block-scoped-container here, we ensure that both 'var x' - // and 'let x' go into the Function-container's locals, and we do get a collision - // conflict. - return isFunctionLike(node.parent) || isClassStaticBlockDeclaration(node.parent) ? ContainerFlags.None : ContainerFlags.IsBlockScopedContainer; - } - - return ContainerFlags.None; - } - - function addToContainerChain(next: Node) { + function addToContainerChain(next: HasLocals) { if (lastContainer) { lastContainer.nextContainer = next; } @@ -2256,8 +2191,6 @@ function createBinder(): (file: SourceFile, options: CompilerOptions) => void { case SyntaxKind.FunctionExpression: case SyntaxKind.ArrowFunction: case SyntaxKind.JSDocFunctionType: - case SyntaxKind.JSDocTypedefTag: - case SyntaxKind.JSDocCallbackTag: case SyntaxKind.ClassStaticBlockDeclaration: case SyntaxKind.TypeAliasDeclaration: case SyntaxKind.MappedType: @@ -2267,6 +2200,7 @@ function createBinder(): (file: SourceFile, options: CompilerOptions) => void { // their container in the tree). To accomplish this, we simply add their declared // symbol to the 'locals' of the container. These symbols can then be found as // the type checker walks up the containers, checking them for matching names. + if (container.locals) Debug.assertNode(container, canHaveLocals); return declareSymbol(container.locals!, /*parent*/ undefined, node, symbolFlags, symbolExcludes); } } @@ -2394,6 +2328,7 @@ function createBinder(): (file: SourceFile, options: CompilerOptions) => void { } // falls through default: + Debug.assertNode(blockScopeContainer, canHaveLocals); if (!blockScopeContainer.locals) { blockScopeContainer.locals = createSymbolTable(); addToContainerChain(blockScopeContainer); @@ -2413,8 +2348,8 @@ function createBinder(): (file: SourceFile, options: CompilerOptions) => void { const saveCurrentFlow = currentFlow; for (const typeAlias of delayedTypeAliases) { const host = typeAlias.parent.parent; - container = findAncestor(host.parent, n => !!(getContainerFlags(n) & ContainerFlags.IsContainer)) || file; - blockScopeContainer = getEnclosingBlockScopeContainer(host) || file; + container = (findAncestor(host.parent, n => !!(getContainerFlags(n) & ContainerFlags.IsContainer)) as IsContainer | undefined) || file; + blockScopeContainer = (getEnclosingBlockScopeContainer(host) as IsBlockScopedContainer | undefined) || file; currentFlow = initFlowNode({ flags: FlowFlags.Start }); parent = typeAlias; bind(typeAlias.typeExpression); @@ -2440,7 +2375,7 @@ function createBinder(): (file: SourceFile, options: CompilerOptions) => void { container = declName.parent.expression; break; case AssignmentDeclarationKind.PrototypeProperty: - container = (declName.parent.expression as PropertyAccessExpression).name; + container = (declName.parent.expression as PropertyAccessEntityNameExpression).name; break; case AssignmentDeclarationKind.Property: container = isExportsOrModuleExportsOrAlias(file, declName.parent.expression) ? file @@ -2733,7 +2668,7 @@ function createBinder(): (file: SourceFile, options: CompilerOptions) => void { bindChildren(node); } else { - bindContainer(node, containerFlags); + bindContainer(node as HasContainerFlags, containerFlags); } parent = saveParent; } @@ -2803,18 +2738,20 @@ function createBinder(): (file: SourceFile, options: CompilerOptions) => void { } // falls through case SyntaxKind.ThisKeyword: + // TODO: Why use `isExpression` here? both Identifier and ThisKeyword are expressions. if (currentFlow && (isExpression(node) || parent.kind === SyntaxKind.ShorthandPropertyAssignment)) { - node.flowNode = currentFlow; + (node as Identifier | ThisExpression).flowNode = currentFlow; } + // TODO: a `ThisExpression` is not an Identifier, this cast is unsound return checkContextualIdentifier(node as Identifier); case SyntaxKind.QualifiedName: if (currentFlow && isPartOfTypeQuery(node)) { - node.flowNode = currentFlow; + (node as QualifiedName).flowNode = currentFlow; } break; case SyntaxKind.MetaProperty: case SyntaxKind.SuperKeyword: - node.flowNode = currentFlow; + (node as MetaProperty | SuperExpression).flowNode = currentFlow; break; case SyntaxKind.PrivateIdentifier: return checkPrivateIdentifier(node as PrivateIdentifier); @@ -2897,7 +2834,7 @@ function createBinder(): (file: SourceFile, options: CompilerOptions) => void { case SyntaxKind.VariableDeclaration: return bindVariableDeclarationOrBindingElement(node as VariableDeclaration); case SyntaxKind.BindingElement: - node.flowNode = currentFlow; + (node as BindingElement).flowNode = currentFlow; return bindVariableDeclarationOrBindingElement(node as BindingElement); case SyntaxKind.PropertyDeclaration: case SyntaxKind.PropertySignature: @@ -2943,7 +2880,7 @@ function createBinder(): (file: SourceFile, options: CompilerOptions) => void { return bindObjectLiteralExpression(node as ObjectLiteralExpression); case SyntaxKind.FunctionExpression: case SyntaxKind.ArrowFunction: - return bindFunctionExpression(node as FunctionExpression); + return bindFunctionExpression(node as FunctionExpression | ArrowFunction); case SyntaxKind.CallExpression: const assignmentKind = getAssignmentDeclarationKind(node as CallExpression); @@ -3208,7 +3145,7 @@ function createBinder(): (file: SourceFile, options: CompilerOptions) => void { if (hasPrivateIdentifier) { return; } - const thisContainer = getThisContainer(node, /*includeArrowFunctions*/ false); + const thisContainer = getThisContainer(node, /*includeArrowFunctions*/ false, /*includeClassComputedPropertyName*/ false); switch (thisContainer.kind) { case SyntaxKind.FunctionDeclaration: case SyntaxKind.FunctionExpression: @@ -3257,7 +3194,7 @@ function createBinder(): (file: SourceFile, options: CompilerOptions) => void { if (hasDynamicName(node)) { break; } - else if ((thisContainer as SourceFile).commonJsModuleIndicator) { + else if (thisContainer.commonJsModuleIndicator) { declareSymbol(thisContainer.symbol.exports!, thisContainer.symbol, node, SymbolFlags.Property | SymbolFlags.ExportValue, SymbolFlags.None); } else { @@ -3497,7 +3434,7 @@ function createBinder(): (file: SourceFile, options: CompilerOptions) => void { return expr.parent; } - function lookupSymbolForPropertyAccess(node: BindableStaticNameExpression, lookupContainer: Node = container): Symbol | undefined { + function lookupSymbolForPropertyAccess(node: BindableStaticNameExpression, lookupContainer: IsContainer | IsBlockScopedContainer | EntityNameExpression = container): Symbol | undefined { if (isIdentifier(node)) { return lookupSymbolForName(lookupContainer, node.escapedText); } @@ -3652,7 +3589,7 @@ function createBinder(): (file: SourceFile, options: CompilerOptions) => void { } } - function bindFunctionExpression(node: FunctionExpression) { + function bindFunctionExpression(node: FunctionExpression | ArrowFunction) { if (!file.isDeclarationFile && !(node.flags & NodeFlags.Ambient)) { if (isAsyncFunction(node)) { emitFlags |= NodeFlags.HasAsyncFunctions; @@ -3687,11 +3624,10 @@ function createBinder(): (file: SourceFile, options: CompilerOptions) => void { function bindTypeParameter(node: TypeParameterDeclaration) { if (isJSDocTemplateTag(node.parent)) { - const container = getEffectiveContainerForJSDocTemplateTag(node.parent); + const container: HasLocals | undefined = getEffectiveContainerForJSDocTemplateTag(node.parent); if (container) { - if (!container.locals) { - container.locals = createSymbolTable(); - } + Debug.assertNode(container, canHaveLocals); + container.locals ??= createSymbolTable(); declareSymbol(container.locals, /*parent*/ undefined, node, SymbolFlags.TypeParameter, SymbolFlags.TypeParameterExcludes); } else { @@ -3699,11 +3635,10 @@ function createBinder(): (file: SourceFile, options: CompilerOptions) => void { } } else if (node.parent.kind === SyntaxKind.InferType) { - const container = getInferTypeContainer(node.parent); + const container: HasLocals | undefined = getInferTypeContainer(node.parent); if (container) { - if (!container.locals) { - container.locals = createSymbolTable(); - } + Debug.assertNode(container, canHaveLocals); + container.locals ??= createSymbolTable(); declareSymbol(container.locals, /*parent*/ undefined, node, SymbolFlags.TypeParameter, SymbolFlags.TypeParameterExcludes); } else { @@ -3823,13 +3758,96 @@ export function isExportsOrModuleExportsOrAlias(sourceFile: SourceFile, node: Ex return false; } +function getContainerFlags(node: Node): ContainerFlags { + switch (node.kind) { + case SyntaxKind.ClassExpression: + case SyntaxKind.ClassDeclaration: + case SyntaxKind.EnumDeclaration: + case SyntaxKind.ObjectLiteralExpression: + case SyntaxKind.TypeLiteral: + case SyntaxKind.JSDocTypeLiteral: + case SyntaxKind.JsxAttributes: + return ContainerFlags.IsContainer; + + case SyntaxKind.InterfaceDeclaration: + return ContainerFlags.IsContainer | ContainerFlags.IsInterface; + + case SyntaxKind.ModuleDeclaration: + case SyntaxKind.TypeAliasDeclaration: + case SyntaxKind.MappedType: + case SyntaxKind.IndexSignature: + return ContainerFlags.IsContainer | ContainerFlags.HasLocals; + + case SyntaxKind.SourceFile: + return ContainerFlags.IsContainer | ContainerFlags.IsControlFlowContainer | ContainerFlags.HasLocals; + + case SyntaxKind.GetAccessor: + case SyntaxKind.SetAccessor: + case SyntaxKind.MethodDeclaration: + if (isObjectLiteralOrClassExpressionMethodOrAccessor(node)) { + return ContainerFlags.IsContainer | ContainerFlags.IsControlFlowContainer | ContainerFlags.HasLocals | ContainerFlags.IsFunctionLike | ContainerFlags.IsObjectLiteralOrClassExpressionMethodOrAccessor; + } + // falls through + case SyntaxKind.Constructor: + case SyntaxKind.FunctionDeclaration: + case SyntaxKind.MethodSignature: + case SyntaxKind.CallSignature: + case SyntaxKind.JSDocSignature: + case SyntaxKind.JSDocFunctionType: + case SyntaxKind.FunctionType: + case SyntaxKind.ConstructSignature: + case SyntaxKind.ConstructorType: + case SyntaxKind.ClassStaticBlockDeclaration: + return ContainerFlags.IsContainer | ContainerFlags.IsControlFlowContainer | ContainerFlags.HasLocals | ContainerFlags.IsFunctionLike; + + case SyntaxKind.FunctionExpression: + case SyntaxKind.ArrowFunction: + return ContainerFlags.IsContainer | ContainerFlags.IsControlFlowContainer | ContainerFlags.HasLocals | ContainerFlags.IsFunctionLike | ContainerFlags.IsFunctionExpression; + + case SyntaxKind.ModuleBlock: + return ContainerFlags.IsControlFlowContainer; + case SyntaxKind.PropertyDeclaration: + return (node as PropertyDeclaration).initializer ? ContainerFlags.IsControlFlowContainer : 0; + + case SyntaxKind.CatchClause: + case SyntaxKind.ForStatement: + case SyntaxKind.ForInStatement: + case SyntaxKind.ForOfStatement: + case SyntaxKind.CaseBlock: + return ContainerFlags.IsBlockScopedContainer | ContainerFlags.HasLocals; + + case SyntaxKind.Block: + // do not treat blocks directly inside a function as a block-scoped-container. + // Locals that reside in this block should go to the function locals. Otherwise 'x' + // would not appear to be a redeclaration of a block scoped local in the following + // example: + // + // function foo() { + // var x; + // let x; + // } + // + // If we placed 'var x' into the function locals and 'let x' into the locals of + // the block, then there would be no collision. + // + // By not creating a new block-scoped-container here, we ensure that both 'var x' + // and 'let x' go into the Function-container's locals, and we do get a collision + // conflict. + return isFunctionLike(node.parent) || isClassStaticBlockDeclaration(node.parent) ? ContainerFlags.None : ContainerFlags.IsBlockScopedContainer | ContainerFlags.HasLocals; + } + + return ContainerFlags.None; +} + function lookupSymbolForName(container: Node, name: __String): Symbol | undefined { - const local = container.locals && container.locals.get(name); + const local = tryCast(container, canHaveLocals)?.locals?.get(name); if (local) { - return local.exportSymbol || local; + return local.exportSymbol ?? local; } if (isSourceFile(container) && container.jsGlobalAugmentations && container.jsGlobalAugmentations.has(name)) { return container.jsGlobalAugmentations.get(name); } - return container.symbol && container.symbol.exports && container.symbol.exports.get(name); + if (canHaveSymbol(container)) { + return container.symbol?.exports?.get(name); + } } diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 62a15349dec20..963981dde4743 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -8,6 +8,7 @@ import { addRelatedInfo, addSyntheticLeadingComment, AllAccessorDeclarations, + AmbientModuleDeclaration, and, AnonymousType, AnyImportOrReExport, @@ -35,6 +36,7 @@ import { BinaryOperatorToken, binarySearch, BindableObjectDefinePropertyCall, + BindableStaticNameExpression, BindingElement, BindingElementGrandparent, BindingName, @@ -49,9 +51,13 @@ import { CancellationToken, canHaveDecorators, canHaveExportModifier, + canHaveFlowNode, canHaveIllegalDecorators, canHaveIllegalModifiers, + canHaveJSDoc, + canHaveLocals, canHaveModifiers, + canHaveSymbol, canUsePropertyAccess, cartesianProduct, CaseBlock, @@ -188,6 +194,7 @@ import { FlowSwitchClause, FlowType, forEach, + forEachAncestor, forEachChild, forEachChildRecursively, forEachEnclosingBlockScopeContainer, @@ -208,6 +215,7 @@ import { FunctionExpression, FunctionFlags, FunctionLikeDeclaration, + FunctionOrConstructorTypeNode, FunctionTypeNode, GenericType, GetAccessorDeclaration, @@ -353,6 +361,7 @@ import { hasJSDocNodes, hasJSDocParameterTags, hasJsonModuleEmitEnabled, + HasLocals, HasModifiers, hasOnlyExpressionInitializer, hasOverrideModifier, @@ -700,7 +709,6 @@ import { JSDocAugmentsTag, JSDocCallbackTag, JSDocComment, - JSDocContainer, JSDocEnumTag, JSDocFunctionType, JSDocImplementsTag, @@ -720,6 +728,7 @@ import { JSDocTemplateTag, JSDocTypedefTag, JSDocTypeExpression, + JSDocTypeLiteral, JSDocTypeReferencingNode, JSDocTypeTag, JSDocVariadicType, @@ -778,6 +787,7 @@ import { ModuleInstanceState, ModuleKind, ModuleResolutionKind, + ModuleSpecifierResolutionHost, NamedDeclaration, NamedExports, NamedImportsOrExports, @@ -1446,6 +1456,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { getSymbolsOfParameterPropertyDeclaration: (parameterIn, parameterName) => { const parameter = getParseTreeNode(parameterIn, isParameter); if (parameter === undefined) return Debug.fail("Cannot get symbols of a synthetic parameter that cannot be resolved to a parse-tree node."); + Debug.assert(isParameterPropertyDeclaration(parameter, parameter.parent)); return getSymbolsOfParameterPropertyDeclaration(parameter, escapeLeadingUnderscores(parameterName)); }, getDeclaredTypeOfSymbol, @@ -2564,6 +2575,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return nodeLinks[nodeId] || (nodeLinks[nodeId] = new (NodeLinks as any)()); } + function tryGetNodeLinks(node: Node): NodeLinks | undefined { + return node.id ? nodeLinks[node.id] : undefined; + } + function isGlobalSourceFile(node: Node) { return node.kind === SyntaxKind.SourceFile && !isExternalOrCommonJsModule(node as SourceFile); } @@ -2594,7 +2609,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { * @param parameterName a name of the parameter to get the symbols for. * @return a tuple of two symbols */ - function getSymbolsOfParameterPropertyDeclaration(parameter: ParameterDeclaration, parameterName: __String): [Symbol, Symbol] { + function getSymbolsOfParameterPropertyDeclaration(parameter: ParameterPropertyDeclaration, parameterName: __String): [Symbol, Symbol] { const constructorDeclaration = parameter.parent; const classDeclaration = parameter.parent.parent; @@ -2742,7 +2757,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (isPropertyDeclaration(declaration) && getContainingClass(usage) === getContainingClass(declaration)) { const propName = declaration.name; if (isIdentifier(propName) || isPrivateIdentifier(propName)) { - const type = getTypeOfSymbol(getSymbolOfNode(declaration)); + const type = getTypeOfSymbol(getSymbolOfDeclaration(declaration)); const staticBlocks = filter(declaration.parent.members, isClassStaticBlockDeclaration); if (isPropertyInitializedInStaticBlocks(propName, type, staticBlocks, declaration.parent.pos, current.pos)) { return true; @@ -2902,7 +2917,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const originalLocation = location; // needed for did-you-mean error reporting, which gathers candidates starting from the original location let result: Symbol | undefined; let lastLocation: Node | undefined; - let lastSelfReferenceLocation: Node | undefined; + let lastSelfReferenceLocation: Declaration | undefined; let propertyWithInvalidInitializer: PropertyDeclaration | undefined; let associatedDeclarationForContainingInitializerOrBindingName: ParameterDeclaration | BindingElement | undefined; let withinDeferredContext = false; @@ -2917,7 +2932,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return undefined; } // Locals of a source file are not in scope (because they get merged into the global symbol table) - if (location.locals && !isGlobalSourceFile(location)) { + if (canHaveLocals(location) && location.locals && !isGlobalSourceFile(location)) { if (result = lookup(location.locals, name, meaning)) { let useResult = true; if (isFunctionLike(location) && lastLocation && lastLocation !== (location as FunctionLikeDeclaration).body) { @@ -2978,7 +2993,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { isInExternalModule = true; // falls through case SyntaxKind.ModuleDeclaration: - const moduleExports = getSymbolOfNode(location as SourceFile | ModuleDeclaration)?.exports || emptySymbols; + const moduleExports = getSymbolOfDeclaration(location as SourceFile | ModuleDeclaration)?.exports || emptySymbols; if (location.kind === SyntaxKind.SourceFile || (isModuleDeclaration(location) && location.flags & NodeFlags.Ambient && !isGlobalScopeAugmentation(location))) { // It's an external module. First see if the module has an export default and if the local @@ -3021,7 +3036,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } break; case SyntaxKind.EnumDeclaration: - if (result = lookup(getSymbolOfNode(location)?.exports || emptySymbols, name, meaning & SymbolFlags.EnumMember)) { + if (result = lookup(getSymbolOfDeclaration(location as EnumDeclaration)?.exports || emptySymbols, name, meaning & SymbolFlags.EnumMember)) { break loop; } break; @@ -3049,7 +3064,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // The below is used to lookup type parameters within a class or interface, as they are added to the class/interface locals // These can never be latebound, so the symbol's raw members are sufficient. `getMembersOfNode` cannot be used, as it would // trigger resolving late-bound names, which we may already be in the process of doing while we're here! - if (result = lookup(getSymbolOfNode(location as ClassLikeDeclaration | InterfaceDeclaration).members || emptySymbols, name, meaning & SymbolFlags.Type)) { + if (result = lookup(getSymbolOfDeclaration(location as ClassLikeDeclaration | InterfaceDeclaration).members || emptySymbols, name, meaning & SymbolFlags.Type)) { if (!isTypeParameterSymbolDeclaredInContainer(result, location)) { // ignore type parameters not declared in this container result = undefined; @@ -3066,8 +3081,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } break loop; } - if (location.kind === SyntaxKind.ClassExpression && meaning & SymbolFlags.Class) { - const className = (location as ClassExpression).name; + if (isClassExpression(location) && meaning & SymbolFlags.Class) { + const className = location.name; if (className && name === className.escapedText) { result = location.symbol; break loop; @@ -3078,7 +3093,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // The type parameters of a class are not in scope in the base class expression. if (lastLocation === (location as ExpressionWithTypeArguments).expression && (location.parent as HeritageClause).token === SyntaxKind.ExtendsKeyword) { const container = location.parent.parent; - if (isClassLike(container) && (result = lookup(getSymbolOfNode(container).members!, name, meaning & SymbolFlags.Type))) { + if (isClassLike(container) && (result = lookup(getSymbolOfDeclaration(container).members!, name, meaning & SymbolFlags.Type))) { if (nameNotFoundMessage) { error(errorLocation, Diagnostics.Base_class_expressions_cannot_reference_class_type_parameters); } @@ -3098,7 +3113,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { grandparent = location.parent.parent; if (isClassLike(grandparent) || grandparent.kind === SyntaxKind.InterfaceDeclaration) { // A reference to this grandparent's type parameters would be an error - if (result = lookup(getSymbolOfNode(grandparent as ClassLikeDeclaration | InterfaceDeclaration).members!, name, meaning & SymbolFlags.Type)) { + if (result = lookup(getSymbolOfDeclaration(grandparent as ClassLikeDeclaration | InterfaceDeclaration).members!, name, meaning & SymbolFlags.Type)) { if (nameNotFoundMessage) { error(errorLocation, Diagnostics.A_computed_property_name_cannot_reference_a_type_parameter_from_its_containing_type); } @@ -3132,7 +3147,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (meaning & SymbolFlags.Function) { const functionName = (location as FunctionExpression).name; if (functionName && name === functionName.escapedText) { - result = location.symbol; + result = (location as FunctionExpression).symbol; break loop; } } @@ -3221,8 +3236,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (!result) { if (lastLocation) { - Debug.assert(lastLocation.kind === SyntaxKind.SourceFile); - if ((lastLocation as SourceFile).commonJsModuleIndicator && name === "exports" && meaning & lastLocation.symbol.flags) { + Debug.assertNode(lastLocation, isSourceFile); + if (lastLocation.commonJsModuleIndicator && name === "exports" && meaning & lastLocation.symbol.flags) { return lastLocation.symbol; } } @@ -3351,7 +3366,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const candidate = getMergedSymbol(getLateBoundSymbol(result)); const root = (getRootDeclaration(associatedDeclarationForContainingInitializerOrBindingName) as ParameterDeclaration); // A parameter initializer or binding pattern initializer within a parameter cannot refer to itself - if (candidate === getSymbolOfNode(associatedDeclarationForContainingInitializerOrBindingName)) { + if (candidate === getSymbolOfDeclaration(associatedDeclarationForContainingInitializerOrBindingName)) { error(errorLocation, Diagnostics.Parameter_0_cannot_reference_itself, declarationNameToString(associatedDeclarationForContainingInitializerOrBindingName.name)); } // And it cannot refer to any declarations which come after it @@ -3405,7 +3420,16 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return !getImmediatelyInvokedFunctionExpression(location); } - function isSelfReferenceLocation(node: Node): boolean { + type SelfReferenceLocation = + | FunctionDeclaration + | ClassDeclaration + | InterfaceDeclaration + | EnumDeclaration + | TypeAliasDeclaration + | ModuleDeclaration + ; + + function isSelfReferenceLocation(node: Node): node is SelfReferenceLocation { switch (node.kind) { case SyntaxKind.FunctionDeclaration: case SyntaxKind.ClassDeclaration: @@ -3443,11 +3467,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return false; } - const container = getThisContainer(errorLocation, /*includeArrowFunctions*/ false); - let location = container; + const container = getThisContainer(errorLocation, /*includeArrowFunctions*/ false, /*includeClassComputedPropertyName*/ false); + let location: Node = container; while (location) { if (isClassLike(location.parent)) { - const classSymbol = getSymbolOfNode(location.parent); + const classSymbol = getSymbolOfDeclaration(location.parent); if (!classSymbol) { break; } @@ -3770,7 +3794,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { function checkAndReportErrorForResolvingImportAliasToTypeOnlySymbol(node: ImportEqualsDeclaration, resolved: Symbol | undefined) { if (markSymbolOfAliasDeclarationIfTypeOnly(node, /*immediateTarget*/ undefined, resolved, /*overwriteEmpty*/ false) && !node.isTypeOnly) { - const typeOnlyDeclaration = getTypeOnlyAliasDeclaration(getSymbolOfNode(node))!; + const typeOnlyDeclaration = getTypeOnlyAliasDeclaration(getSymbolOfDeclaration(node))!; const isExport = typeOnlyDeclaration.kind === SyntaxKind.ExportSpecifier; const message = isExport ? Diagnostics.An_import_alias_cannot_reference_a_declaration_that_was_exported_using_export_type @@ -4080,7 +4104,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } function reportNonExportedMember(node: Node, name: Identifier, declarationName: string, moduleSymbol: Symbol, moduleName: string): void { - const localSymbol = moduleSymbol.valueDeclaration?.locals?.get(name.escapedText); + const localSymbol = tryCast(moduleSymbol.valueDeclaration, canHaveLocals)?.locals?.get(name.escapedText); const exports = moduleSymbol.exports; if (localSymbol) { const exportedEqualsSymbol = exports?.get(InternalSymbolName.ExportEquals); @@ -4149,10 +4173,12 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } } - function getTargetOfNamespaceExportDeclaration(node: NamespaceExportDeclaration, dontResolveAlias: boolean): Symbol { - const resolved = resolveExternalModuleSymbol(node.parent.symbol, dontResolveAlias); - markSymbolOfAliasDeclarationIfTypeOnly(node, /*immediateTarget*/ undefined, resolved, /*overwriteEmpty*/ false); - return resolved; + function getTargetOfNamespaceExportDeclaration(node: NamespaceExportDeclaration, dontResolveAlias: boolean): Symbol | undefined { + if (canHaveSymbol(node.parent)) { + const resolved = resolveExternalModuleSymbol(node.parent.symbol, dontResolveAlias); + markSymbolOfAliasDeclarationIfTypeOnly(node, /*immediateTarget*/ undefined, resolved, /*overwriteEmpty*/ false); + return resolved; + } } function getTargetOfExportSpecifier(node: ExportSpecifier, meaning: SymbolFlags, dontResolveAlias?: boolean) { @@ -4356,7 +4382,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // If the declaration itself is type-only, mark it and return. // No need to check what it resolves to. - const sourceSymbol = getSymbolOfNode(aliasDeclaration); + const sourceSymbol = getSymbolOfDeclaration(aliasDeclaration); if (isTypeOnlyImportOrExportDeclaration(aliasDeclaration)) { const links = getSymbolLinks(sourceSymbol); links.typeOnlyDeclaration = aliasDeclaration; @@ -4393,7 +4419,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } function markExportAsReferenced(node: ImportEqualsDeclaration | ExportSpecifier) { - const symbol = getSymbolOfNode(node); + const symbol = getSymbolOfDeclaration(node); const target = resolveAlias(symbol); if (target) { const markAlias = target === unknownSymbol || @@ -4607,14 +4633,14 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const host = getJSDocHost(node); if (host && isExpressionStatement(host) && isPrototypePropertyAssignment(host.expression)) { // /** @param {K} p */ X.prototype.m = function () { } <-- look for K on X's declaration - const symbol = getSymbolOfNode(host.expression.left); + const symbol = getSymbolOfDeclaration(host.expression.left); if (symbol) { return getDeclarationOfJSPrototypeContainer(symbol); } } if (host && isFunctionExpression(host) && isPrototypePropertyAssignment(host.parent) && isExpressionStatement(host.parent.parent)) { // X.prototype.m = /** @param {K} p */ function () { } <-- look for K on X's declaration - const symbol = getSymbolOfNode(host.parent.left); + const symbol = getSymbolOfDeclaration(host.parent.left); if (symbol) { return getDeclarationOfJSPrototypeContainer(symbol); } @@ -4623,14 +4649,14 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { isBinaryExpression(host.parent.parent) && getAssignmentDeclarationKind(host.parent.parent) === AssignmentDeclarationKind.Prototype) { // X.prototype = { /** @param {K} p */m() { } } <-- look for K on X's declaration - const symbol = getSymbolOfNode(host.parent.parent.left); + const symbol = getSymbolOfDeclaration(host.parent.parent.left as BindableStaticNameExpression); if (symbol) { return getDeclarationOfJSPrototypeContainer(symbol); } } const sig = getEffectiveJSDocHost(node); if (sig && isFunctionLike(sig)) { - const symbol = getSymbolOfNode(sig); + const symbol = getSymbolOfDeclaration(sig); return symbol && symbol.valueDeclaration; } } @@ -5172,12 +5198,18 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return symbol && symbol.mergeId && (merged = mergedSymbols[symbol.mergeId]) ? merged : symbol; } - function getSymbolOfNode(node: Declaration): Symbol; - function getSymbolOfNode(node: Node): Symbol | undefined; - function getSymbolOfNode(node: Node): Symbol | undefined { + function getSymbolOfDeclaration(node: Declaration): Symbol { return getMergedSymbol(node.symbol && getLateBoundSymbol(node.symbol)); } + /** + * Get the merged symbol for a node. If you know the node is a `Declaration`, it is faster and more type safe to + * use use `getSymbolOfDeclaration` instead. + */ + function getSymbolOfNode(node: Node): Symbol | undefined { + return canHaveSymbol(node) ? getSymbolOfDeclaration(node) : undefined; + } + function getParentOfSymbol(symbol: Symbol): Symbol | undefined { return getMergedSymbol(symbol.parent && getLateBoundSymbol(symbol.parent)); } @@ -5212,7 +5244,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const otherFiles = host.getSourceFiles(); for (const file of otherFiles) { if (!isExternalModule(file)) continue; - const sym = getSymbolOfNode(file); + const sym = getSymbolOfDeclaration(file); const ref = getAliasForSymbolInContainer(sym, symbol); if (!ref) continue; results = append(results, sym); @@ -5260,16 +5292,16 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (!isAmbientModule(d) && d.parent){ // direct children of a module if (hasNonGlobalAugmentationExternalModuleSymbol(d.parent)) { - return getSymbolOfNode(d.parent); + return getSymbolOfDeclaration(d.parent as Declaration); } // export ='d member of an ambient module - if (isModuleBlock(d.parent) && d.parent.parent && resolveExternalModuleSymbol(getSymbolOfNode(d.parent.parent)) === symbol) { - return getSymbolOfNode(d.parent.parent); + if (isModuleBlock(d.parent) && d.parent.parent && resolveExternalModuleSymbol(getSymbolOfDeclaration(d.parent.parent)) === symbol) { + return getSymbolOfDeclaration(d.parent.parent); } } if (isClassExpression(d) && isBinaryExpression(d.parent) && d.parent.operatorToken.kind === SyntaxKind.EqualsToken && isAccessExpression(d.parent.left) && isEntityNameExpression(d.parent.left.expression)) { if (isModuleExportsAccessExpression(d.parent.left) || isExportsIdentifier(d.parent.left.expression)) { - return getSymbolOfNode(getSourceFileOfNode(d)); + return getSymbolOfDeclaration(getSourceFileOfNode(d)); } checkExpressionCached(d.parent.left.expression); return getNodeLinks(d.parent.left.expression).resolvedSymbol; @@ -5292,7 +5324,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const firstDecl: Node | false = !!length(symbol.declarations) && first(symbol.declarations!); if (meaning & SymbolFlags.Value && firstDecl && firstDecl.parent && isVariableDeclaration(firstDecl.parent)) { if (isObjectLiteralExpression(firstDecl) && firstDecl === firstDecl.parent.initializer || isTypeLiteralNode(firstDecl) && firstDecl === firstDecl.parent.type) { - return getSymbolOfNode(firstDecl.parent); + return getSymbolOfDeclaration(firstDecl.parent); } } } @@ -5469,7 +5501,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { let result: T; for (let location = enclosingDeclaration; location; location = location.parent) { // Locals of a source file are not in scope (because they get merged into the global symbol table) - if (location.locals && !isGlobalSourceFile(location)) { + if (canHaveLocals(location) && location.locals && !isGlobalSourceFile(location)) { if (result = callback(location.locals, /*ignoreQualification*/ undefined, /*isLocalNameLookup*/ true, location)) { return result; } @@ -5481,7 +5513,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } // falls through case SyntaxKind.ModuleDeclaration: - const sym = getSymbolOfNode(location as ModuleDeclaration); + const sym = getSymbolOfDeclaration(location as ModuleDeclaration); // `sym` may not have exports if this module declaration is backed by the symbol for a `const` that's being rewritten // into a namespace - in such cases, it's best to just let the namespace appear empty (the const members couldn't have referred // to one another anyway) @@ -5501,7 +5533,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // trigger resolving late-bound names, which we may already be in the process of doing while we're here! let table: UnderscoreEscapedMap | undefined; // TODO: Should this filtered table be cached in some way? - (getSymbolOfNode(location as ClassLikeDeclaration | InterfaceDeclaration).members || emptySymbols).forEach((memberSymbol, key) => { + (getSymbolOfDeclaration(location as ClassLikeDeclaration | InterfaceDeclaration).members || emptySymbols).forEach((memberSymbol, key) => { if (memberSymbol.flags & (SymbolFlags.Type & ~SymbolFlags.Assignment)) { (table || (table = createSymbolTable())).set(key, memberSymbol); } @@ -5803,7 +5835,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { function getExternalModuleContainer(declaration: Node) { const node = findAncestor(declaration, hasExternalModuleSymbol); - return node && getSymbolOfNode(node); + return node && getSymbolOfDeclaration(node as AmbientModuleDeclaration | SourceFile); } function hasExternalModuleSymbol(declaration: Node) { @@ -5907,7 +5939,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (symbol && symbol.flags & SymbolFlags.TypeParameter && meaning & SymbolFlags.Type) { return { accessibility: SymbolAccessibility.Accessible }; } - if (!symbol && isThisIdentifier(firstIdentifier) && isSymbolAccessible(getSymbolOfNode(getThisContainer(firstIdentifier, /*includeArrowFunctions*/ false)), firstIdentifier, meaning, /*computeAliases*/ false).accessibility === SymbolAccessibility.Accessible) { + if (!symbol && isThisIdentifier(firstIdentifier) && isSymbolAccessible(getSymbolOfDeclaration(getThisContainer(firstIdentifier, /*includeArrowFunctions*/ false, /*includeClassComputedPropertyName*/ false)), firstIdentifier, meaning, /*computeAliases*/ false).accessibility === SymbolAccessibility.Accessible) { return { accessibility: SymbolAccessibility.Accessible }; } @@ -5970,7 +6002,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { function typeToString(type: Type, enclosingDeclaration?: Node, flags: TypeFormatFlags = TypeFormatFlags.AllowUniqueESSymbolType | TypeFormatFlags.UseAliasDefinedOutsideCurrentScope, writer: EmitTextWriter = createTextWriter("")): string { const noTruncation = compilerOptions.noErrorTruncation || flags & TypeFormatFlags.NoTruncation; - const typeNode = nodeBuilder.typeToTypeNode(type, enclosingDeclaration, toNodeBuilderFlags(flags) | NodeBuilderFlags.IgnoreErrors | (noTruncation ? NodeBuilderFlags.NoTruncation : 0), writer); + const typeNode = nodeBuilder.typeToTypeNode(type, enclosingDeclaration, toNodeBuilderFlags(flags) | NodeBuilderFlags.IgnoreErrors | (noTruncation ? NodeBuilderFlags.NoTruncation : 0)); if (typeNode === undefined) return Debug.fail("should always get typenode"); // The unresolved type gets a synthesized comment on `any` to hint to users that it's not a plain `any`. // Otherwise, we always strip comments out. @@ -6054,23 +6086,14 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { function withContext(enclosingDeclaration: Node | undefined, flags: NodeBuilderFlags | undefined, tracker: SymbolTracker | undefined, cb: (context: NodeBuilderContext) => T): T | undefined { Debug.assert(enclosingDeclaration === undefined || (enclosingDeclaration.flags & NodeFlags.Synthesized) === 0); + const moduleResolverHost = + tracker?.trackSymbol ? tracker.moduleResolverHost : + flags! & NodeBuilderFlags.DoNotIncludeSymbolChain ? createBasicNodeBuilderModuleSpecifierResolutionHost(host) : + undefined; const context: NodeBuilderContext = { enclosingDeclaration, flags: flags || NodeBuilderFlags.None, - // If no full tracker is provided, fake up a dummy one with a basic limited-functionality moduleResolverHost - tracker: tracker && tracker.trackSymbol ? tracker : { trackSymbol: () => false, moduleResolverHost: flags! & NodeBuilderFlags.DoNotIncludeSymbolChain ? { - getCommonSourceDirectory: !!(host as Program).getCommonSourceDirectory ? () => (host as Program).getCommonSourceDirectory() : () => "", - getCurrentDirectory: () => host.getCurrentDirectory(), - getSymlinkCache: maybeBind(host, host.getSymlinkCache), - getPackageJsonInfoCache: () => host.getPackageJsonInfoCache?.(), - useCaseSensitiveFileNames: maybeBind(host, host.useCaseSensitiveFileNames), - redirectTargetsMap: host.redirectTargetsMap, - getProjectReferenceRedirect: fileName => host.getProjectReferenceRedirect(fileName), - isSourceOfProjectReferenceRedirect: fileName => host.isSourceOfProjectReferenceRedirect(fileName), - fileExists: fileName => host.fileExists(fileName), - getFileIncludeReasons: () => host.getFileIncludeReasons(), - readFile: host.readFile ? (fileName => host.readFile!(fileName)) : undefined, - } : undefined }, + tracker: undefined!, encounteredError: false, reportedDiagnostic: false, visitedTypes: undefined, @@ -6078,45 +6101,14 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { inferTypeParameters: undefined, approximateLength: 0 }; - context.tracker = wrapSymbolTrackerToReportForContext(context, context.tracker); + context.tracker = new SymbolTrackerImpl(context, tracker, moduleResolverHost); const resultingNode = cb(context); if (context.truncating && context.flags & NodeBuilderFlags.NoTruncation) { - context.tracker?.reportTruncationError?.(); + context.tracker.reportTruncationError(); } return context.encounteredError ? undefined : resultingNode; } - function wrapSymbolTrackerToReportForContext(context: NodeBuilderContext, tracker: SymbolTracker): SymbolTracker { - const oldTrackSymbol = tracker.trackSymbol; - return { - ...tracker, - reportCyclicStructureError: wrapReportedDiagnostic(tracker.reportCyclicStructureError), - reportInaccessibleThisError: wrapReportedDiagnostic(tracker.reportInaccessibleThisError), - reportInaccessibleUniqueSymbolError: wrapReportedDiagnostic(tracker.reportInaccessibleUniqueSymbolError), - reportLikelyUnsafeImportRequiredError: wrapReportedDiagnostic(tracker.reportLikelyUnsafeImportRequiredError), - reportNonlocalAugmentation: wrapReportedDiagnostic(tracker.reportNonlocalAugmentation), - reportPrivateInBaseOfClassExpression: wrapReportedDiagnostic(tracker.reportPrivateInBaseOfClassExpression), - reportNonSerializableProperty: wrapReportedDiagnostic(tracker.reportNonSerializableProperty), - trackSymbol: oldTrackSymbol && ((...args) => { - const result = oldTrackSymbol(...args); - if (result) { - context.reportedDiagnostic = true; - } - return result; - }), - }; - - function wrapReportedDiagnostic any>(method: T | undefined): T | undefined { - if (!method) { - return method; - } - return (((...args) => { - context.reportedDiagnostic = true; - return method(...args); - }) as T); - } - } - function checkTruncationLength(context: NodeBuilderContext): boolean { if (context.truncating) return context.truncating; return context.truncating = context.approximateLength > ((context.flags & NodeBuilderFlags.NoTruncation) ? noTruncationMaximumTruncationLength : defaultMaximumTruncationLength); @@ -6264,9 +6256,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (!context.encounteredError && !(context.flags & NodeBuilderFlags.AllowThisInObjectLiteral)) { context.encounteredError = true; } - if (context.tracker.reportInaccessibleThisError) { - context.tracker.reportInaccessibleThisError(); - } + context.tracker.reportInaccessibleThisError?.(); } context.approximateLength += 4; return factory.createThisTypeNode(); @@ -6566,7 +6556,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { context.truncating = true; } context.approximateLength += cachedResult.addedLength; - return deepCloneOrReuseNode(cachedResult) as TypeNode as T; + return deepCloneOrReuseNode(cachedResult.node) as T; } let depth: number | undefined; @@ -6582,11 +6572,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const result = transform(type); const addedLength = context.approximateLength - startLength; if (!context.reportedDiagnostic && !context.encounteredError) { - if (context.truncating) { - (result as any).truncating = true; - } - (result as any).addedLength = addedLength; - links?.serializedTypes?.set(key, result as TypeNode as TypeNode & {truncating?: boolean, addedLength: number}); + links?.serializedTypes?.set(key, { node: result, truncating: context.truncating, addedLength }); } context.visitedTypes.delete(typeId); if (id) { @@ -6907,7 +6893,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { anyType : getNonMissingTypeOfSymbol(propertySymbol); const saveEnclosingDeclaration = context.enclosingDeclaration; context.enclosingDeclaration = undefined; - if (context.tracker.trackSymbol && isLateBoundName(propertySymbol.escapedName)) { + if (context.tracker.canTrackSymbol && isLateBoundName(propertySymbol.escapedName)) { if (propertySymbol.declarations) { const decl = first(propertySymbol.declarations); if (hasLateBindableName(decl)) { @@ -6922,7 +6908,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } } } - else if (context.tracker?.reportNonSerializableProperty) { + else { context.tracker.reportNonSerializableProperty(symbolToString(propertySymbol)); } } @@ -7226,7 +7212,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { function cloneBindingName(node: BindingName): BindingName { return elideInitializerAndSetEmitFlags(node) as BindingName; function elideInitializerAndSetEmitFlags(node: Node): Node { - if (context.tracker.trackSymbol && isComputedPropertyName(node) && isLateBindableName(node)) { + if (context.tracker.canTrackSymbol && isComputedPropertyName(node) && isLateBindableName(node)) { trackComputedName(node.expression, context.enclosingDeclaration, context); } let visited = visitEachChild(node, elideInitializerAndSetEmitFlags, nullTransformationContext, /*nodesVisitor*/ undefined, elideInitializerAndSetEmitFlags)!; @@ -7247,7 +7233,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } function trackComputedName(accessExpression: EntityNameOrEntityNameExpression, enclosingDeclaration: Node | undefined, context: NodeBuilderContext) { - if (!context.tracker.trackSymbol) return; + if (!context.tracker.canTrackSymbol) return; // get symbol of the first identifier of the entityName const firstIdentifier = getFirstIdentifier(accessExpression); const name = resolveName(firstIdentifier, firstIdentifier.escapedText, SymbolFlags.Value | SymbolFlags.ExportValue, /*nodeNotFoundErrorMessage*/ undefined, /*nameArg*/ undefined, /*isUse*/ true); @@ -7257,7 +7243,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } function lookupSymbolChain(symbol: Symbol, context: NodeBuilderContext, meaning: SymbolFlags, yieldModuleSymbol?: boolean) { - context.tracker.trackSymbol!(symbol, context.enclosingDeclaration, meaning); // TODO: GH#18217 + context.tracker.trackSymbol(symbol, context.enclosingDeclaration, meaning); return lookupSymbolChainWorker(symbol, context, meaning, yieldModuleSymbol); } @@ -7726,7 +7712,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } if (!expression) { expression = setEmitFlags(factory.createIdentifier(symbolName, typeParameterNodes), EmitFlags.NoAsciiEscaping); - expression.symbol = symbol; + (expression as Identifier).symbol = symbol; } return factory.createElementAccessExpression(createExpressionFromSymbolChain(chain, index - 1), expression); } @@ -7797,7 +7783,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (initial.typeParameterSymbolList) { initial.typeParameterSymbolList = new Set(initial.typeParameterSymbolList); } - initial.tracker = wrapSymbolTrackerToReportForContext(initial, initial.tracker); + initial.tracker = new SymbolTrackerImpl(initial, initial.tracker.inner, initial.tracker.moduleResolverHost); return initial; } @@ -7879,7 +7865,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { introducesError = true; } else { - context.tracker?.trackSymbol?.(sym, context.enclosingDeclaration, SymbolFlags.All); + context.tracker.trackSymbol(sym, context.enclosingDeclaration, SymbolFlags.All); includePrivateSymbol?.(sym); } if (isIdentifier(node)) { @@ -8086,25 +8072,26 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { ...oldcontext, usedSymbolNames: new Set(oldcontext.usedSymbolNames), remappedSymbolNames: new Map(), - tracker: { - ...oldcontext.tracker, - trackSymbol: (sym, decl, meaning) => { - const accessibleResult = isSymbolAccessible(sym, decl, meaning, /*computeAliases*/ false); - if (accessibleResult.accessibility === SymbolAccessibility.Accessible) { - // Lookup the root symbol of the chain of refs we'll use to access it and serialize it - const chain = lookupSymbolChainWorker(sym, context, meaning); - if (!(sym.flags & SymbolFlags.Property)) { - includePrivateSymbol(chain[0]); - } - } - else if (oldcontext.tracker && oldcontext.tracker.trackSymbol) { - return oldcontext.tracker.trackSymbol(sym, decl, meaning); + tracker: undefined!, + }; + const tracker: SymbolTracker = { + ...oldcontext.tracker.inner, + trackSymbol: (sym, decl, meaning) => { + const accessibleResult = isSymbolAccessible(sym, decl, meaning, /*computeAliases*/ false); + if (accessibleResult.accessibility === SymbolAccessibility.Accessible) { + // Lookup the root symbol of the chain of refs we'll use to access it and serialize it + const chain = lookupSymbolChainWorker(sym, context, meaning); + if (!(sym.flags & SymbolFlags.Property)) { + includePrivateSymbol(chain[0]); } - return false; - }, + } + else if (oldcontext.tracker.inner?.trackSymbol) { + return oldcontext.tracker.inner.trackSymbol(sym, decl, meaning); + } + return false; }, }; - context.tracker = wrapSymbolTrackerToReportForContext(context, context.tracker); + context.tracker = new SymbolTrackerImpl(context, tracker, oldcontext.tracker.moduleResolverHost); forEachEntry(symbolTable, (symbol, name) => { const baseName = unescapeLeadingUnderscores(name); void getInternalSymbolName(symbol, baseName); // Called to cache values into `usedSymbolNames` and `remappedSymbolNames` @@ -8405,7 +8392,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { ), ModifierFlags.None ); - context.tracker.trackSymbol!(type.symbol, context.enclosingDeclaration, SymbolFlags.Value); + context.tracker.trackSymbol(type.symbol, context.enclosingDeclaration, SymbolFlags.Value); } else { const statement = setTextRange(factory.createVariableStatement(/*modifiers*/ undefined, factory.createVariableDeclarationList([ @@ -9099,8 +9086,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // issue a visibility error on it. Only anonymous classes that an alias points at _would_ issue // a visibility error here (as they're not visible within any scope), but we want to hoist them // into the containing scope anyway, so we want to skip the visibility checks. - const oldTrack = context.tracker.trackSymbol; - context.tracker.trackSymbol = () => false; + const prevDisableTrackSymbol = context.tracker.disableTrackSymbol; + context.tracker.disableTrackSymbol = true; if (isExportAssignmentCompatibleSymbolName) { results.push(factory.createExportAssignment( /*modifiers*/ undefined, @@ -9128,7 +9115,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { serializeExportSpecifier(name, varName); } } - context.tracker.trackSymbol = oldTrack; + context.tracker.disableTrackSymbol = prevDisableTrackSymbol; return true; } else { @@ -9520,8 +9507,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { function getTypeAliasForTypeLiteral(type: Type): Symbol | undefined { if (type.symbol && type.symbol.flags & SymbolFlags.TypeLiteral && type.symbol.declarations) { const node = walkUpParenthesizedTypes(type.symbol.declarations[0].parent); - if (node.kind === SyntaxKind.TypeAliasDeclaration) { - return getSymbolOfNode(node); + if (isTypeAliasDeclaration(node)) { + return getSymbolOfDeclaration(node); } } return undefined; @@ -9533,28 +9520,6 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { isExternalModuleAugmentation(node.parent.parent); } - interface NodeBuilderContext { - enclosingDeclaration: Node | undefined; - flags: NodeBuilderFlags; - tracker: SymbolTracker; - - // State - encounteredError: boolean; - reportedDiagnostic: boolean; - visitedTypes: Set | undefined; - symbolDepth: Map | undefined; - inferTypeParameters: TypeParameter[] | undefined; - approximateLength: number; - truncating?: boolean; - typeParameterSymbolList?: Set; - typeParameterNames?: Map; - typeParameterNamesByText?: Set; - typeParameterNamesByTextNextNameCount?: Map; - usedSymbolNames?: Set; - remappedSymbolNames?: Map; - reverseMappedStack?: ReverseMappedSymbol[]; - } - function isDefaultBindingContext(location: Node) { return location.kind === SyntaxKind.SourceFile || isAmbientModule(location); } @@ -9907,7 +9872,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (checkMode !== CheckMode.Normal) { return getTypeForVariableLikeDeclaration(node, /*includeOptionality*/ false, checkMode); } - const symbol = getSymbolOfNode(node); + const symbol = getSymbolOfDeclaration(node); return symbol && getSymbolLinks(symbol).type || getTypeForVariableLikeDeclaration(node, /*includeOptionality*/ false, checkMode); } @@ -9989,7 +9954,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { function getSyntheticElementAccess(node: BindingElement | PropertyAssignment | ShorthandPropertyAssignment | Expression): ElementAccessExpression | undefined { const parentAccess = getParentElementAccess(node); - if (parentAccess && parentAccess.flowNode) { + if (parentAccess && canHaveFlowNode(parentAccess) && parentAccess.flowNode) { const propName = getDestructuringPropertyName(node); if (propName) { const literal = setTextRange(parseNodeFactory.createStringLiteral(propName), node); @@ -10196,7 +10161,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const func = declaration.parent as FunctionLikeDeclaration; // For a parameter of a set accessor, use the type of the get accessor if one is present if (func.kind === SyntaxKind.SetAccessor && hasBindableName(func)) { - const getter = getDeclarationOfKind(getSymbolOfNode(declaration.parent), SyntaxKind.GetAccessor); + const getter = getDeclarationOfKind(getSymbolOfDeclaration(declaration.parent), SyntaxKind.GetAccessor); if (getter) { const getterSignature = getSignatureFromDeclaration(getter); const thisParameter = getAccessorThisParameter(func as AccessorDeclaration); @@ -10221,7 +10186,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // not a parameter of a contextually typed function if (hasOnlyExpressionInitializer(declaration) && !!declaration.initializer) { if (isInJSFile(declaration) && !isParameter(declaration)) { - const containerObjectType = getJSContainerObjectType(declaration, getSymbolOfNode(declaration), getDeclaredExpandoInitializer(declaration)); + const containerObjectType = getJSContainerObjectType(declaration, getSymbolOfDeclaration(declaration), getDeclaredExpandoInitializer(declaration)); if (containerObjectType) { return containerObjectType; } @@ -10297,7 +10262,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return; } for (const declaration of symbol.declarations) { - const container = getThisContainer(declaration, /*includeArrowFunctions*/ false); + const container = getThisContainer(declaration, /*includeArrowFunctions*/ false, /*includeClassComputedPropertyName*/ false); if (container && (container.kind === SyntaxKind.Constructor || isJSConstructor(container))) { return container as ConstructorDeclaration; } @@ -10606,7 +10571,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } function isDeclarationInConstructor(expression: Expression) { - const thisContainer = getThisContainer(expression, /*includeArrowFunctions*/ false); + const thisContainer = getThisContainer(expression, /*includeArrowFunctions*/ false, /*includeClassComputedPropertyName*/ false); // Properties defined in a constructor (or base constructor, or javascript constructor function) don't get undefined added. // Function expressions that are assigned to the prototype count as methods. return thisContainer.kind === SyntaxKind.Constructor || @@ -10745,7 +10710,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } // always widen a 'unique symbol' type if the type was created for a different declaration. - if (type.flags & TypeFlags.UniqueESSymbol && (isBindingElement(declaration) || !declaration.type) && type.symbol !== getSymbolOfNode(declaration)) { + if (type.flags & TypeFlags.UniqueESSymbol && (isBindingElement(declaration) || !declaration.type) && type.symbol !== getSymbolOfDeclaration(declaration)) { type = esSymbolType; } @@ -10818,7 +10783,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return anyType; } if (symbol.flags & SymbolFlags.ModuleExports && symbol.valueDeclaration) { - const fileSymbol = getSymbolOfNode(getSourceFileOfNode(symbol.valueDeclaration)); + const fileSymbol = getSymbolOfDeclaration(getSourceFileOfNode(symbol.valueDeclaration)); const result = createSymbol(fileSymbol.flags, "exports" as __String); result.declarations = fileSymbol.declarations ? fileSymbol.declarations.slice() : []; result.parent = symbol; @@ -11258,7 +11223,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // in-place and returns the same array. function appendTypeParameters(typeParameters: TypeParameter[] | undefined, declarations: readonly TypeParameterDeclaration[]): TypeParameter[] | undefined { for (const declaration of declarations) { - typeParameters = appendIfUnique(typeParameters, getDeclaredTypeOfTypeParameter(getSymbolOfNode(declaration))); + typeParameters = appendIfUnique(typeParameters, getDeclaredTypeOfTypeParameter(getSymbolOfDeclaration(declaration))); } return typeParameters; } @@ -11271,7 +11236,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // prototype assignments get the outer type parameters of their constructor function const assignmentKind = getAssignmentDeclarationKind(node); if (assignmentKind === AssignmentDeclarationKind.Prototype || assignmentKind === AssignmentDeclarationKind.PrototypeProperty) { - const symbol = getSymbolOfNode(node.left); + const symbol = getSymbolOfDeclaration(node.left as BindableStaticNameExpression | PropertyAssignment); if (symbol && symbol.parent && !findAncestor(symbol.parent.valueDeclaration, d => node === d)) { node = symbol.parent.valueDeclaration!; } @@ -11303,7 +11268,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { case SyntaxKind.ConditionalType: { const outerTypeParameters = getOuterTypeParameters(node, includeThisTypes); if (node.kind === SyntaxKind.MappedType) { - return append(outerTypeParameters, getDeclaredTypeOfTypeParameter(getSymbolOfNode((node as MappedTypeNode).typeParameter))); + return append(outerTypeParameters, getDeclaredTypeOfTypeParameter(getSymbolOfDeclaration((node as MappedTypeNode).typeParameter))); } else if (node.kind === SyntaxKind.ConditionalType) { return concatenate(outerTypeParameters, getInferTypeParameters(node as ConditionalTypeNode)); @@ -11311,7 +11276,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const outerAndOwnTypeParameters = appendTypeParameters(outerTypeParameters, getEffectiveTypeParameterDeclarations(node as DeclarationWithTypeParameters)); const thisType = includeThisTypes && (node.kind === SyntaxKind.ClassDeclaration || node.kind === SyntaxKind.ClassExpression || node.kind === SyntaxKind.InterfaceDeclaration || isJSConstructor(node)) && - getDeclaredTypeOfClassOrInterface(getSymbolOfNode(node as ClassLikeDeclaration | InterfaceDeclaration)).thisType; + getDeclaredTypeOfClassOrInterface(getSymbolOfDeclaration(node as ClassLikeDeclaration | InterfaceDeclaration)).thisType; return thisType ? append(outerAndOwnTypeParameters, thisType) : outerAndOwnTypeParameters; } case SyntaxKind.JSDocParameterTag: @@ -11754,7 +11719,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (declaration.kind === SyntaxKind.EnumDeclaration) { for (const member of (declaration as EnumDeclaration).members) { if (hasBindableName(member)) { - const memberSymbol = getSymbolOfNode(member); + const memberSymbol = getSymbolOfDeclaration(member); const value = getEnumMemberValue(member); const memberType = value !== undefined ? getFreshTypeOfLiteralType(getEnumLiteralType(value, getSymbolId(symbol), memberSymbol)) : @@ -12979,7 +12944,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { function getTypeParameterFromMappedType(type: MappedType) { return type.typeParameter || - (type.typeParameter = getDeclaredTypeOfTypeParameter(getSymbolOfNode(type.declaration.typeParameter))); + (type.typeParameter = getDeclaredTypeOfTypeParameter(getSymbolOfDeclaration(type.declaration.typeParameter))); } function getConstraintTypeFromMappedType(type: MappedType) { @@ -14143,7 +14108,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { hasBindableName(declaration) && (!hasThisParameter || !thisParameter)) { const otherKind = declaration.kind === SyntaxKind.GetAccessor ? SyntaxKind.SetAccessor : SyntaxKind.GetAccessor; - const other = getDeclarationOfKind(getSymbolOfNode(declaration), otherKind); + const other = getDeclarationOfKind(getSymbolOfDeclaration(declaration), otherKind); if (other) { thisParameter = getAnnotatedAccessorThisParameter(other); } @@ -14401,7 +14366,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (jsDocType) { return jsDocType; } - const setter = getDeclarationOfKind(getSymbolOfNode(declaration), SyntaxKind.SetAccessor); + const setter = getDeclarationOfKind(getSymbolOfDeclaration(declaration), SyntaxKind.SetAccessor); const setterType = getAnnotatedAccessorType(setter); if (setterType) { return setterType; @@ -14643,7 +14608,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const checkMappedType = (grandParent.parent as ConditionalTypeNode).checkType as MappedTypeNode; const nodeType = getTypeFromTypeNode(checkMappedType.type!); inferences = append(inferences, instantiateType(nodeType, - makeUnaryTypeMapper(getDeclaredTypeOfTypeParameter(getSymbolOfNode(checkMappedType.typeParameter)), checkMappedType.typeParameter.constraint ? getTypeFromTypeNode(checkMappedType.typeParameter.constraint) : keyofConstraintType) + makeUnaryTypeMapper(getDeclaredTypeOfTypeParameter(getSymbolOfDeclaration(checkMappedType.typeParameter)), checkMappedType.typeParameter.constraint ? getTypeFromTypeNode(checkMappedType.typeParameter.constraint) : keyofConstraintType) )); } } @@ -17508,7 +17473,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { function getTypeFromInferTypeNode(node: InferTypeNode): Type { const links = getNodeLinks(node); if (!links.resolvedType) { - links.resolvedType = getDeclaredTypeOfTypeParameter(getSymbolOfNode(node.typeParameter)); + links.resolvedType = getDeclaredTypeOfTypeParameter(getSymbolOfDeclaration(node.typeParameter)); } return links.resolvedType; } @@ -17599,7 +17564,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } } - function getTypeFromTypeLiteralOrFunctionOrConstructorTypeNode(node: TypeNode): Type { + function getTypeFromTypeLiteralOrFunctionOrConstructorTypeNode(node: TypeLiteralNode | FunctionOrConstructorTypeNode | JSDocTypeLiteral | JSDocFunctionType | JSDocSignature): Type { const links = getNodeLinks(node); if (!links.resolvedType) { // Deferred resolution of members is handled by resolveObjectTypeMembers @@ -17625,7 +17590,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { while (isParenthesizedTypeNode(host) || isJSDocTypeExpression(host) || isTypeOperatorNode(host) && host.operator === SyntaxKind.ReadonlyKeyword) { host = host.parent; } - return isTypeAlias(host) ? getSymbolOfNode(host) : undefined; + return isTypeAlias(host) ? getSymbolOfDeclaration(host) : undefined; } function getTypeArgumentsForAliasSymbol(symbol: Symbol | undefined) { @@ -17884,12 +17849,12 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } function getThisType(node: Node): Type { - const container = getThisContainer(node, /*includeArrowFunctions*/ false); + const container = getThisContainer(node, /*includeArrowFunctions*/ false, /*includeClassComputedPropertyName*/ false); const parent = container && container.parent; if (parent && (isClassLike(parent) || parent.kind === SyntaxKind.InterfaceDeclaration)) { if (!isStatic(container) && (!isConstructorDeclaration(container) || isNodeDescendantOf(node, container.body))) { - return getDeclaredTypeOfClassOrInterface(getSymbolOfNode(parent as ClassLikeDeclaration | InterfaceDeclaration)).thisType!; + return getDeclaredTypeOfClassOrInterface(getSymbolOfDeclaration(parent as ClassLikeDeclaration | InterfaceDeclaration)).thisType!; } } @@ -17905,7 +17870,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } // inside constructor function C() { ... } if (isJSConstructor(container) && isNodeDescendantOf(node, container.body)) { - return getDeclaredTypeOfClassOrInterface(getSymbolOfNode(container)).thisType!; + return getDeclaredTypeOfClassOrInterface(getSymbolOfDeclaration(container)).thisType!; } error(node, Diagnostics.A_this_type_is_available_only_in_a_non_static_member_of_a_class_or_interface); return errorType; @@ -18026,7 +17991,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { case SyntaxKind.JSDocTypeLiteral: case SyntaxKind.JSDocFunctionType: case SyntaxKind.JSDocSignature: - return getTypeFromTypeLiteralOrFunctionOrConstructorTypeNode(node); + return getTypeFromTypeLiteralOrFunctionOrConstructorTypeNode(node as TypeLiteralNode | FunctionOrConstructorTypeNode | JSDocTypeLiteral | JSDocFunctionType | JSDocSignature); case SyntaxKind.TypeOperator: return getTypeFromTypeOperatorNode(node as TypeOperatorNode); case SyntaxKind.IndexedAccessType: @@ -18964,12 +18929,13 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } function checkExpressionForMutableLocationWithContextualType(next: Expression, sourcePropType: Type) { - next.contextualType = sourcePropType; + const links = getNodeLinks(next); + links.contextualType = sourcePropType; try { return checkExpressionForMutableLocation(next, CheckMode.Contextual, sourcePropType); } finally { - next.contextualType = undefined; + links.contextualType = undefined; } } @@ -19212,18 +19178,19 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } // recreate a tuple from the elements, if possible // Since we're re-doing the expression type, we need to reapply the contextual type - const oldContext = node.contextualType; - node.contextualType = target; + const links = getNodeLinks(node); + const oldContext = links.contextualType; + links.contextualType = target; try { const tupleizedType = checkArrayLiteral(node, CheckMode.Contextual, /*forceTuple*/ true); - node.contextualType = oldContext; + links.contextualType = oldContext; if (isTupleLikeType(tupleizedType)) { return elaborateElementwise(generateLimitedTupleElements(node, target), tupleizedType, target, relation, containingMessageChain, errorOutputContainer); } return false; } finally { - node.contextualType = oldContext; + links.contextualType = oldContext; } } @@ -19231,7 +19198,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (!length(node.properties)) return; for (const prop of node.properties) { if (isSpreadAssignment(prop)) continue; - const type = getLiteralTypeFromProperty(getSymbolOfNode(prop), TypeFlags.StringOrNumberLiteralOrUnique); + const type = getLiteralTypeFromProperty(getSymbolOfDeclaration(prop), TypeFlags.StringOrNumberLiteralOrUnique); if (!type || (type.flags & TypeFlags.Never)) { continue; } @@ -24650,8 +24617,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return isThisInTypeQuery(source) ? target.kind === SyntaxKind.ThisKeyword : target.kind === SyntaxKind.Identifier && getResolvedSymbol(source as Identifier) === getResolvedSymbol(target as Identifier) || - (target.kind === SyntaxKind.VariableDeclaration || target.kind === SyntaxKind.BindingElement) && - getExportSymbolOfValueSymbolIfExported(getResolvedSymbol(source as Identifier)) === getSymbolOfNode(target); + (isVariableDeclaration(target) || isBindingElement(target)) && + getExportSymbolOfValueSymbolIfExported(getResolvedSymbol(source as Identifier)) === getSymbolOfDeclaration(target); case SyntaxKind.ThisKeyword: return target.kind === SyntaxKind.ThisKeyword; case SyntaxKind.SuperKeyword: @@ -25724,7 +25691,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return false; } - function getFlowTypeOfReference(reference: Node, declaredType: Type, initialType = declaredType, flowContainer?: Node, flowNode = reference.flowNode) { + function getFlowTypeOfReference(reference: Node, declaredType: Type, initialType = declaredType, flowContainer?: Node, flowNode = tryCast(reference, canHaveFlowNode)?.flowNode) { let key: string | undefined; let isKeySet = false; let flowDepth = 0; @@ -27175,7 +27142,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // When we emit a class expression with static members that contain a reference // to the constructor in the initializer, we will need to substitute that // binding with an alias as the class name is not in scope. - let container = getThisContainer(node, /*includeArrowFunctions*/ false); + let container = getThisContainer(node, /*includeArrowFunctions*/ false, /*includeClassComputedPropertyName*/ false); while (container.kind !== SyntaxKind.SourceFile) { if (container.parent === declaration) { if (isPropertyDeclaration(container) && isStatic(container) || isClassStaticBlockDeclaration(container)) { @@ -27185,7 +27152,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { break; } - container = getThisContainer(container, /*includeArrowFunctions*/ false); + container = getThisContainer(container, /*includeArrowFunctions*/ false, /*includeClassComputedPropertyName*/ false); } } } @@ -27395,7 +27362,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { function isBindingCapturedByNode(node: Node, decl: VariableDeclaration | BindingElement) { const links = getNodeLinks(node); - return !!links && contains(links.capturedBlockScopeBindings, getSymbolOfNode(decl)); + return !!links && contains(links.capturedBlockScopeBindings, getSymbolOfDeclaration(decl)); } function isAssignedInBodyOfForStatement(node: Identifier, container: ForStatement): boolean { @@ -27447,7 +27414,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { * @param classDecl a class declaration to check if it extends null */ function classDeclarationExtendsNull(classDecl: ClassDeclaration): boolean { - const classSymbol = getSymbolOfNode(classDecl); + const classSymbol = getSymbolOfDeclaration(classDecl); const classInstanceType = getDeclaredTypeOfSymbol(classSymbol) as InterfaceType; const baseConstructorType = getBaseConstructorTypeOfClass(classInstanceType); @@ -27461,7 +27428,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // If a containing class does not have extends clause or the class extends null // skip checking whether super statement is called before "this" accessing. if (baseTypeNode && !classDeclarationExtendsNull(containingClassDecl)) { - if (node.flowNode && !isPostSuperFlowNode(node.flowNode, /*noCacheCheck*/ false)) { + if (canHaveFlowNode(node) && node.flowNode && !isPostSuperFlowNode(node.flowNode, /*noCacheCheck*/ false)) { error(node, diagnosticMessage); } } @@ -27478,38 +27445,51 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const isNodeInTypeQuery = isInTypeQuery(node); // Stop at the first arrow function so that we can // tell whether 'this' needs to be captured. - let container = getThisContainer(node, /* includeArrowFunctions */ true); + let container = getThisContainer(node, /* includeArrowFunctions */ true, /*includeClassComputedPropertyName*/ true); let capturedByArrowFunction = false; + let thisInComputedPropertyName = false; if (container.kind === SyntaxKind.Constructor) { checkThisBeforeSuper(node, container, Diagnostics.super_must_be_called_before_accessing_this_in_the_constructor_of_a_derived_class); } - // Now skip arrow functions to get the "real" owner of 'this'. - if (container.kind === SyntaxKind.ArrowFunction) { - container = getThisContainer(container, /* includeArrowFunctions */ false); - capturedByArrowFunction = true; + while (true) { + // Now skip arrow functions to get the "real" owner of 'this'. + if (container.kind === SyntaxKind.ArrowFunction) { + container = getThisContainer(container, /* includeArrowFunctions */ false, !thisInComputedPropertyName); + capturedByArrowFunction = true; + } + + if (container.kind === SyntaxKind.ComputedPropertyName) { + container = getThisContainer(container, !capturedByArrowFunction, /*includeClassComputedPropertyName*/ false); + thisInComputedPropertyName = true; + continue; + } + + break; } checkThisInStaticClassFieldInitializerInDecoratedClass(node, container); - switch (container.kind) { - case SyntaxKind.ModuleDeclaration: - error(node, Diagnostics.this_cannot_be_referenced_in_a_module_or_namespace_body); - // do not return here so in case if lexical this is captured - it will be reflected in flags on NodeLinks - break; - case SyntaxKind.EnumDeclaration: - error(node, Diagnostics.this_cannot_be_referenced_in_current_location); - // do not return here so in case if lexical this is captured - it will be reflected in flags on NodeLinks - break; - case SyntaxKind.Constructor: - if (isInConstructorArgumentInitializer(node, container)) { - error(node, Diagnostics.this_cannot_be_referenced_in_constructor_arguments); + if (thisInComputedPropertyName) { + error(node, Diagnostics.this_cannot_be_referenced_in_a_computed_property_name); + } + else { + switch (container.kind) { + case SyntaxKind.ModuleDeclaration: + error(node, Diagnostics.this_cannot_be_referenced_in_a_module_or_namespace_body); // do not return here so in case if lexical this is captured - it will be reflected in flags on NodeLinks - } - break; - case SyntaxKind.ComputedPropertyName: - error(node, Diagnostics.this_cannot_be_referenced_in_a_computed_property_name); - break; + break; + case SyntaxKind.EnumDeclaration: + error(node, Diagnostics.this_cannot_be_referenced_in_current_location); + // do not return here so in case if lexical this is captured - it will be reflected in flags on NodeLinks + break; + case SyntaxKind.Constructor: + if (isInConstructorArgumentInitializer(node, container)) { + error(node, Diagnostics.this_cannot_be_referenced_in_constructor_arguments); + // do not return here so in case if lexical this is captured - it will be reflected in flags on NodeLinks + } + break; + } } // When targeting es6, mark that we'll need to capture `this` in its lexically bound scope. @@ -27537,7 +27517,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return type || anyType; } - function tryGetThisTypeAt(node: Node, includeGlobalThis = true, container = getThisContainer(node, /*includeArrowFunctions*/ false)): Type | undefined { + function tryGetThisTypeAt(node: Node, includeGlobalThis = true, container = getThisContainer(node, /*includeArrowFunctions*/ false, /*includeClassComputedPropertyName*/ false)): Type | undefined { const isInJS = isInJSFile(node); if (isFunctionLike(container) && (!isInParameterInitializerBeforeContainingFunction(node) || getThisParameter(container))) { @@ -27564,7 +27544,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } if (isClassLike(container.parent)) { - const symbol = getSymbolOfNode(container.parent); + const symbol = getSymbolOfDeclaration(container.parent); const type = isStatic(container) ? getTypeOfSymbol(symbol) : (getDeclaredTypeOfSymbol(symbol) as InterfaceType).thisType!; return getFlowTypeOfReference(node, type); } @@ -27572,7 +27552,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (isSourceFile(container)) { // look up in the source file's locals or exports if (container.commonJsModuleIndicator) { - const fileSymbol = getSymbolOfNode(container); + const fileSymbol = getSymbolOfDeclaration(container); return fileSymbol && getTypeOfSymbol(fileSymbol); } else if (container.externalModuleIndicator) { @@ -27586,7 +27566,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } function getExplicitThisType(node: Expression) { - const container = getThisContainer(node, /*includeArrowFunctions*/ false); + const container = getThisContainer(node, /*includeArrowFunctions*/ false, /*includeClassComputedPropertyName*/ false); if (isFunctionLike(container)) { const signature = getSignatureFromDeclaration(container); if (signature.thisParameter) { @@ -27594,7 +27574,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } } if (isClassLike(container.parent)) { - const symbol = getSymbolOfNode(container.parent); + const symbol = getSymbolOfDeclaration(container.parent); return isStatic(container) ? getTypeOfSymbol(symbol) : (getDeclaredTypeOfSymbol(symbol) as InterfaceType).thisType!; } } @@ -27690,10 +27670,9 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (container && hasSyntacticModifier(container, ModifierFlags.Async)) inAsyncFunction = true; } - const canUseSuperExpression = isLegalUsageOfSuperExpression(container); let nodeCheckFlag: NodeCheckFlags = 0; - if (!canUseSuperExpression) { + if (!container || !isLegalUsageOfSuperExpression(container)) { // issue more specific error if super is used in computed property name // class A { foo() { return "1" }} // class B { @@ -27715,7 +27694,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return errorType; } - if (!isCallExpression && immediateContainer.kind === SyntaxKind.Constructor) { + if (!isCallExpression && immediateContainer!.kind === SyntaxKind.Constructor) { checkThisBeforeSuper(node, container, Diagnostics.super_must_be_called_before_accessing_a_property_of_super_in_the_constructor_of_a_derived_class); } @@ -27833,7 +27812,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return errorType; } - const classType = getDeclaredTypeOfSymbol(getSymbolOfNode(classLikeDeclaration)) as InterfaceType; + const classType = getDeclaredTypeOfSymbol(getSymbolOfDeclaration(classLikeDeclaration)) as InterfaceType; const baseClassType = classType && getBaseTypes(classType)[0]; if (!baseClassType) { return errorType; @@ -27850,10 +27829,6 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { : getTypeWithThisArgument(baseClassType, classType.thisType); function isLegalUsageOfSuperExpression(container: Node): boolean { - if (!container) { - return false; - } - if (isCallExpression) { // TS 1.0 SPEC (April 2014): 4.8.1 // Super calls are only permitted in constructors of derived classes @@ -28040,7 +28015,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { function getContextualTypeForStaticPropertyDeclaration(declaration: PropertyDeclaration, contextFlags: ContextFlags | undefined): Type | undefined { const parentType = isExpression(declaration.parent) && getContextualType(declaration.parent, contextFlags); if (!parentType) return undefined; - return getTypeOfPropertyOfContextualType(parentType, getSymbolOfNode(declaration).escapedName); + return getTypeOfPropertyOfContextualType(parentType, getSymbolOfDeclaration(declaration).escapedName); } // In a variable, parameter or property declaration with a type annotation, @@ -28238,7 +28213,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { * getSymbolAtLocation would (as that could be reentrant into contextual typing) */ function getSymbolForExpression(e: Expression) { - if (e.symbol) { + if (canHaveSymbol(e) && e.symbol) { return e.symbol; } if (isIdentifier(e)) { @@ -28290,7 +28265,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } // If `binaryExpression.left` was assigned a symbol, then this is a new declaration; otherwise it is an assignment to an existing declaration. // See `bindStaticPropertyAssignment` in `binder.ts`. - else if (!binaryExpression.left.symbol) { + else if (!canHaveSymbol(binaryExpression.left) || !binaryExpression.left.symbol) { return getTypeOfExpression(binaryExpression.left); } else { @@ -28325,7 +28300,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { case AssignmentDeclarationKind.ModuleExports: let valueDeclaration: Declaration | undefined; if (kind !== AssignmentDeclarationKind.ModuleExports) { - valueDeclaration = binaryExpression.left.symbol?.valueDeclaration; + valueDeclaration = canHaveSymbol(binaryExpression.left) ? binaryExpression.left.symbol?.valueDeclaration : undefined; } valueDeclaration ||= binaryExpression.symbol?.valueDeclaration; const annotated = valueDeclaration && getEffectiveTypeAnnotationNode(valueDeclaration); @@ -28363,7 +28338,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } } const thisAccess = cast(binaryExpression.left, isAccessExpression); - if (!isObjectLiteralMethod(getThisContainer(thisAccess.expression, /*includeArrowFunctions*/ false))) { + if (!isObjectLiteralMethod(getThisContainer(thisAccess.expression, /*includeArrowFunctions*/ false, /*includeClassComputedPropertyName*/ false))) { return undefined; } const thisType = checkThisExpression(thisAccess.expression); @@ -28427,7 +28402,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // For a (non-symbol) computed property, there is no reason to look up the name // in the type. It will just be "__computed", which does not appear in any // SymbolTable. - const symbol = getSymbolOfNode(element); + const symbol = getSymbolOfDeclaration(element); return getTypeOfPropertyOfContextualType(type, symbol.escapedName, getSymbolLinks(symbol).nameType); } if (element.name) { @@ -28641,8 +28616,9 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // We cannot answer semantic questions within a with block, do not proceed any further return undefined; } - if (node.contextualType) { - return node.contextualType; + const contextualType = tryGetNodeLinks(node)?.contextualType; + if (contextualType) { + return contextualType; } const { parent } = node; switch (parent.kind) { @@ -28712,16 +28688,18 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } function getInferenceContext(node: Node) { - const ancestor = findAncestor(node, n => !!n.inferenceContext); - return ancestor && ancestor.inferenceContext!; + return forEachAncestor(node, n => tryGetNodeLinks(n)?.inferenceContext); } function getContextualJsxElementAttributesType(node: JsxOpeningLikeElement, contextFlags: ContextFlags | undefined) { - if (isJsxOpeningElement(node) && node.parent.contextualType && contextFlags !== ContextFlags.Completions) { - // Contextually applied type is moved from attributes up to the outer jsx attributes so when walking up from the children they get hit - // _However_ to hit them from the _attributes_ we must look for them here; otherwise we'll used the declared type - // (as below) instead! - return node.parent.contextualType; + if (isJsxOpeningElement(node) && contextFlags !== ContextFlags.Completions) { + const contextualType = tryGetNodeLinks(node.parent)?.contextualType; + if (contextualType) { + // Contextually applied type is moved from attributes up to the outer jsx attributes so when walking up from the children they get hit + // _However_ to hit them from the _attributes_ we must look for them here; otherwise we'll used the declared type + // (as below) instead! + return contextualType; + } } return getContextualTypeForArgumentAtIndex(node, 0); } @@ -29257,7 +29235,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { let offset = 0; for (const memberDecl of node.properties) { - let member = getSymbolOfNode(memberDecl); + let member = getSymbolOfDeclaration(memberDecl); const computedNameType = memberDecl.name && memberDecl.name.kind === SyntaxKind.ComputedPropertyName ? checkComputedPropertyName(memberDecl.name) : undefined; if (memberDecl.kind === SyntaxKind.PropertyAssignment || @@ -30244,7 +30222,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // Find the first enclosing class that has the declaring classes of the protected constituents // of the property as base classes let enclosingClass = forEachEnclosingClass(location, enclosingDeclaration => { - const enclosingClass = getDeclaredTypeOfSymbol(getSymbolOfNode(enclosingDeclaration)!) as InterfaceType; + const enclosingClass = getDeclaredTypeOfSymbol(getSymbolOfDeclaration(enclosingDeclaration)!) as InterfaceType; return isClassDerivedFromDeclaringClasses(enclosingClass, prop, writing); }); // A protected property is accessible if the property is within the declaring class or classes derived from it @@ -30295,7 +30273,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } function getThisParameterFromNodeContext(node: Node) { - const thisContainer = getThisContainer(node, /* includeArrowFunctions */ false); + const thisContainer = getThisContainer(node, /* includeArrowFunctions */ false, /*includeClassComputedPropertyName*/ false); return thisContainer && isFunctionLike(thisContainer) ? getThisParameter(thisContainer) : undefined; } @@ -30540,7 +30518,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { function isThisPropertyAccessInConstructor(node: ElementAccessExpression | PropertyAccessExpression | QualifiedName, prop: Symbol) { return (isConstructorDeclaredProperty(prop) || isThisProperty(node) && isAutoTypedProperty(prop)) - && getThisContainer(node, /*includeArrowFunctions*/ true) === getDeclaringConstructor(prop); + && getThisContainer(node, /*includeArrowFunctions*/ true, /*includeClassComputedPropertyName*/ false) === getDeclaringConstructor(prop); } function checkPropertyAccessExpressionOrQualifiedName(node: PropertyAccessExpression | QualifiedName, left: Expression | QualifiedName, leftType: Type, right: Identifier | PrivateIdentifier, checkMode: CheckMode | undefined) { @@ -31168,7 +31146,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (initializer.kind === SyntaxKind.VariableDeclarationList) { const variable = (initializer as VariableDeclarationList).declarations[0]; if (variable && !isBindingPattern(variable.name)) { - return getSymbolOfNode(variable); + return getSymbolOfDeclaration(variable); } } else if (initializer.kind === SyntaxKind.Identifier) { @@ -31290,7 +31268,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { let spliceIndex: number; Debug.assert(!result.length); for (const signature of signatures) { - const symbol = signature.declaration && getSymbolOfNode(signature.declaration); + const symbol = signature.declaration && getSymbolOfDeclaration(signature.declaration); const parent = signature.declaration && signature.declaration.parent; if (!lastSymbol || symbol === lastSymbol) { if (lastParent && parent === lastParent) { @@ -31936,14 +31914,14 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // For a class decorator, the `target` is the type of the class (e.g. the // "static" or "constructor" side of the class). return [ - createSyntheticExpression(expr, getTypeOfSymbol(getSymbolOfNode(parent))) + createSyntheticExpression(expr, getTypeOfSymbol(getSymbolOfDeclaration(parent))) ]; case SyntaxKind.Parameter: // A parameter declaration decorator will have three arguments (see // `ParameterDecorator` in core.d.ts). const func = parent.parent as FunctionLikeDeclaration; return [ - createSyntheticExpression(expr, parent.parent.kind === SyntaxKind.Constructor ? getTypeOfSymbol(getSymbolOfNode(func)) : errorType), + createSyntheticExpression(expr, parent.parent.kind === SyntaxKind.Constructor ? getTypeOfSymbol(getSymbolOfDeclaration(func)) : errorType), createSyntheticExpression(expr, anyType), createSyntheticExpression(expr, numberType) ]; @@ -33185,7 +33163,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (isPropertyAssignment(walkUpParenthesizedExpressions(func.parent))) return false; // If the symbol of the node has members, treat it like a constructor. - const symbol = getSymbolOfNode(func); + const symbol = getSymbolOfDeclaration(func); return !!symbol?.members?.size; } return false; @@ -33216,7 +33194,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const assignmentSymbol = decl && getSymbolOfExpando(decl, /*allowDeclaration*/ true); const prototype = assignmentSymbol?.exports?.get("prototype" as __String); const init = prototype?.valueDeclaration && getAssignedJSPrototype(prototype.valueDeclaration); - return init ? getSymbolOfNode(init) : undefined; + return init ? getSymbolOfDeclaration(init) : undefined; } function getSymbolOfExpando(node: Node, allowDeclaration: boolean): Symbol | undefined { @@ -33265,7 +33243,6 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return getSymbolOfNode(decl); } - function getAssignedJSPrototype(node: Node) { if (!node.parent) { return false; @@ -33721,11 +33698,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return errorType; } else if (container.kind === SyntaxKind.Constructor) { - const symbol = getSymbolOfNode(container.parent as ClassLikeDeclaration); + const symbol = getSymbolOfDeclaration(container.parent); return getTypeOfSymbol(symbol); } else { - const symbol = getSymbolOfNode(container)!; + const symbol = getSymbolOfDeclaration(container)!; return getTypeOfSymbol(symbol); } } @@ -34053,7 +34030,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (!isOmittedExpression(element)) { const type = getBindingElementTypeFromParentType(element, parentType); if (element.name.kind === SyntaxKind.Identifier) { - getSymbolLinks(getSymbolOfNode(element)).type = type; + getSymbolLinks(getSymbolOfDeclaration(element)).type = type; } else { assignBindingElementTypes(element.name, type); @@ -34481,7 +34458,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { contextuallyCheckFunctionExpressionOrObjectLiteralMethod(node, checkMode); - return getTypeOfSymbol(getSymbolOfNode(node)); + return getTypeOfSymbol(getSymbolOfDeclaration(node)); } function contextuallyCheckFunctionExpressionOrObjectLiteralMethod(node: FunctionExpression | ArrowFunction | MethodDeclaration, checkMode?: CheckMode) { @@ -34494,7 +34471,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // already assigned contextual types. if (!(links.flags & NodeCheckFlags.ContextChecked)) { links.flags |= NodeCheckFlags.ContextChecked; - const signature = firstOrUndefined(getSignaturesOfType(getTypeOfSymbol(getSymbolOfNode(node)), SignatureKind.Call)); + const signature = firstOrUndefined(getSignaturesOfType(getTypeOfSymbol(getSymbolOfDeclaration(node)), SignatureKind.Call)); if (!signature) { return; } @@ -35965,11 +35942,12 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { function checkExpressionWithContextualType(node: Expression, contextualType: Type, inferenceContext: InferenceContext | undefined, checkMode: CheckMode): Type { const context = getContextNode(node); - const saveContextualType = context.contextualType; - const saveInferenceContext = context.inferenceContext; + const links = getNodeLinks(context); + const saveContextualType = links.contextualType; + const saveInferenceContext = links.inferenceContext; try { - context.contextualType = contextualType; - context.inferenceContext = inferenceContext; + links.contextualType = contextualType; + links.inferenceContext = inferenceContext; const type = checkExpression(node, checkMode | CheckMode.Contextual | (inferenceContext ? CheckMode.Inferential : 0)); // In CheckMode.Inferential we collect intra-expression inference sites to process before fixing any type // parameters. This information is no longer needed after the call to checkExpression. @@ -35987,8 +35965,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // In the event our operation is canceled or some other exception occurs, reset the contextual type // so that we do not accidentally hold onto an instance of the checker, as a Type created in the services layer // may hold onto the checker that created it. - context.contextualType = saveContextualType; - context.inferenceContext = saveInferenceContext; + links.contextualType = saveContextualType; + links.inferenceContext = saveInferenceContext; } } @@ -36353,8 +36331,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (links.contextFreeType) { return links.contextFreeType; } - const saveContextualType = node.contextualType; - node.contextualType = anyType; + const saveContextualType = links.contextualType; + links.contextualType = anyType; try { const type = links.contextFreeType = checkExpression(node, CheckMode.SkipContextSensitive); return type; @@ -36363,7 +36341,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // In the event our operation is canceled or some other exception occurs, reset the contextual type // so that we do not accidentally hold onto an instance of the checker, as a Type created in the services layer // may hold onto the checker that created it. - node.contextualType = saveContextualType; + links.contextualType = saveContextualType; } } @@ -36546,7 +36524,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { checkSourceElement(node.constraint); checkSourceElement(node.default); - const typeParameter = getDeclaredTypeOfTypeParameter(getSymbolOfNode(node)); + const typeParameter = getDeclaredTypeOfTypeParameter(getSymbolOfDeclaration(node)); // Resolve base constraint to reveal circularity errors getBaseConstraintOfType(typeParameter); if (!hasNonCircularTypeParameterDefault(typeParameter)) { @@ -36563,10 +36541,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { function checkTypeParameterDeferred(node: TypeParameterDeclaration) { if (isInterfaceDeclaration(node.parent) || isClassLike(node.parent) || isTypeAliasDeclaration(node.parent)) { - const typeParameter = getDeclaredTypeOfTypeParameter(getSymbolOfNode(node)); + const typeParameter = getDeclaredTypeOfTypeParameter(getSymbolOfDeclaration(node)); const modifiers = getVarianceModifiers(typeParameter); if (modifiers) { - const symbol = getSymbolOfNode(node.parent); + const symbol = getSymbolOfDeclaration(node.parent); if (isTypeAliasDeclaration(node.parent) && !(getObjectFlags(getDeclaredTypeOfSymbol(symbol)) & (ObjectFlags.Anonymous | ObjectFlags.Mapped))) { error(node, Diagnostics.Variance_annotations_are_only_supported_in_type_aliases_for_object_function_constructor_and_mapped_types); } @@ -36912,7 +36890,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { case "arguments": case "prototype": const message = Diagnostics.Static_property_0_conflicts_with_built_in_property_Function_0_of_constructor_function_1; - const className = getNameOfSymbolAsWritten(getSymbolOfNode(node)); + const className = getNameOfSymbolAsWritten(getSymbolOfDeclaration(node)); error(memberNameNode, message, memberName, className); break; } @@ -36949,9 +36927,9 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } } - function checkTypeForDuplicateIndexSignatures(node: Node) { + function checkTypeForDuplicateIndexSignatures(node: ClassLikeDeclaration | InterfaceDeclaration | TypeLiteralNode) { if (node.kind === SyntaxKind.InterfaceDeclaration) { - const nodeSymbol = getSymbolOfNode(node as InterfaceDeclaration); + const nodeSymbol = getSymbolOfDeclaration(node); // in case of merging interface declaration it is possible that we'll enter this check procedure several times for every declaration // to prevent this run check only for the first declaration of a given kind if (nodeSymbol.declarations && nodeSymbol.declarations.length > 0 && nodeSymbol.declarations[0] !== node) { @@ -36962,7 +36940,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // TypeScript 1.0 spec (April 2014) // 3.7.4: An object type can contain at most one string index signature and one numeric index signature. // 8.5: A class declaration can have at most one string index member declaration and one numeric index member declaration - const indexSymbol = getIndexSymbol(getSymbolOfNode(node)!); + const indexSymbol = getIndexSymbol(getSymbolOfDeclaration(node)!); if (indexSymbol?.declarations) { const indexSignatureMap = new Map(); for (const declaration of (indexSymbol.declarations as IndexSignatureDeclaration[])) { @@ -37065,7 +37043,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { checkSourceElement(node.body); - const symbol = getSymbolOfNode(node); + const symbol = getSymbolOfDeclaration(node); const firstDeclaration = getDeclarationOfKind(symbol, node.kind); // Only type check the symbol once @@ -37198,7 +37176,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (hasBindableName(node)) { // TypeScript 1.0 spec (April 2014): 8.4.3 // Accessors for the same member name must specify the same accessibility. - const symbol = getSymbolOfNode(node); + const symbol = getSymbolOfDeclaration(node); const getter = getDeclarationOfKind(symbol, SyntaxKind.GetAccessor); const setter = getDeclarationOfKind(symbol, SyntaxKind.SetAccessor); if (getter && setter && !(getNodeCheckFlags(getter) & NodeCheckFlags.TypeChecked)) { @@ -37222,7 +37200,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } } } - const returnType = getTypeOfAccessors(getSymbolOfNode(node)); + const returnType = getTypeOfAccessors(getSymbolOfDeclaration(node)); if (node.kind === SyntaxKind.GetAccessor) { checkAllCodePathsInNonVoidFunctionReturnOrThrow(node, returnType); } @@ -37470,7 +37448,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { grammarErrorOnNode(node, Diagnostics.infer_declarations_are_only_permitted_in_the_extends_clause_of_a_conditional_type); } checkSourceElement(node.typeParameter); - const symbol = getSymbolOfNode(node.typeParameter); + const symbol = getSymbolOfDeclaration(node.typeParameter); if (symbol.declarations && symbol.declarations.length > 1) { const links = getSymbolLinks(symbol); if (!links.typeParametersChecked) { @@ -37814,7 +37792,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (!symbol) { // local symbol is undefined => this declaration is non-exported. // however symbol might contain other declarations that are exported - symbol = getSymbolOfNode(node)!; + symbol = getSymbolOfDeclaration(node)!; if (!symbol.exportSymbol) { // this is a pure local symbol (all declarations are non-exported) - no need to check anything return; @@ -37906,7 +37884,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { case SyntaxKind.NamespaceImport: case SyntaxKind.ImportClause: let result = DeclarationSpaces.None; - const target = resolveAlias(getSymbolOfNode(d)!); + const target = resolveAlias(getSymbolOfDeclaration(d as ImportEqualsDeclaration | NamespaceImport | ImportClause | ExportAssignment | BinaryExpression)!); forEach(target.declarations, d => { result |= getDeclarationSpaces(d); }); @@ -38387,7 +38365,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { switch (node.parent.kind) { case SyntaxKind.ClassDeclaration: headMessage = Diagnostics.Decorator_function_return_type_0_is_not_assignable_to_type_1; - const classSymbol = getSymbolOfNode(node.parent); + const classSymbol = getSymbolOfDeclaration(node.parent); const classConstructorType = getTypeOfSymbol(classSymbol); expectedReturnType = getUnionType([classConstructorType, voidType]); break; @@ -38568,7 +38546,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { case SyntaxKind.GetAccessor: case SyntaxKind.SetAccessor: const otherKind = node.kind === SyntaxKind.GetAccessor ? SyntaxKind.SetAccessor : SyntaxKind.GetAccessor; - const otherAccessor = getDeclarationOfKind(getSymbolOfNode(node), otherKind); + const otherAccessor = getDeclarationOfKind(getSymbolOfDeclaration(node), otherKind); markDecoratorMedataDataTypeNodeAsReferenced(getAnnotatedAccessorTypeNode(node) || otherAccessor && getAnnotatedAccessorTypeNode(otherAccessor)); break; case SyntaxKind.MethodDeclaration: @@ -38726,7 +38704,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // first we want to check the local symbol that contain this declaration // - if node.localSymbol !== undefined - this is current declaration is exported and localSymbol points to the local symbol // - if node.localSymbol === undefined - this node is non-exported so we can just pick the result of getSymbolOfNode - const symbol = getSymbolOfNode(node); + const symbol = getSymbolOfDeclaration(node); const localSymbol = node.localSymbol || symbol; // Since the javascript won't do semantic analysis like typescript, @@ -38870,7 +38848,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // Already would have reported an error on the getter. break; } - const symbol = getSymbolOfNode(member); + const symbol = getSymbolOfDeclaration(member); if (!symbol.isReferenced && (hasEffectiveModifier(member, ModifierFlags.Private) || isNamedDeclaration(member) && isPrivateIdentifier(member.name)) && !(member.flags & NodeFlags.Ambient)) { @@ -38905,7 +38883,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { function checkUnusedTypeParameters(node: ClassLikeDeclaration | SignatureDeclaration | InterfaceDeclaration | TypeAliasDeclaration, addDiagnostic: AddUnusedDiagnostic): void { // Only report errors on the last declaration for the type parameter container; // this ensures that all uses have been accounted for. - const declarations = getSymbolOfNode(node).declarations; + const declarations = getSymbolOfDeclaration(node).declarations; if (!declarations || last(declarations) !== node) return; const typeParameters = getEffectiveTypeParameterDeclarations(node); @@ -38971,7 +38949,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { (isVariableDeclaration(declaration) && isForInOrOfStatement(declaration.parent.parent) || isImportedDeclaration(declaration)) && isIdentifierThatStartsWithUnderscore(declaration.name!); } - function checkUnusedLocalsAndParameters(nodeWithLocals: Node, addDiagnostic: AddUnusedDiagnostic): void { + function checkUnusedLocalsAndParameters(nodeWithLocals: HasLocals, addDiagnostic: AddUnusedDiagnostic): void { // Ideally we could use the ImportClause directly as a key, but must wait until we have full ES6 maps. So must store key along with value. const unusedImports = new Map(); const unusedDestructures = new Map(); @@ -39071,7 +39049,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { function checkPotentialUncheckedRenamedBindingElementsInTypes() { for (const node of potentialUnusedRenamedBindingElementsInTypes) { - if (!getSymbolOfNode(node)?.isReferenced) { + if (!getSymbolOfDeclaration(node)?.isReferenced) { const wrappingDeclaration = walkUpBindingElementsAndPatterns(node); Debug.assert(isParameterDeclaration(wrappingDeclaration), "Only parameter declaration should be checked here"); const diagnostic = createDiagnosticForNode(node.name, Diagnostics._0_is_an_unused_renaming_of_1_Did_you_intend_to_use_it_as_a_type_annotation, declarationNameToString(node.name), declarationNameToString(node.propertyName)); @@ -39364,7 +39342,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return; } - const symbol = getSymbolOfNode(node); + const symbol = getSymbolOfDeclaration(node); if (symbol.flags & SymbolFlags.FunctionScopedVariable) { if (!isIdentifier(node.name)) return Debug.fail(); const localDeclarationSymbol = resolveName(node, node.name.escapedText, SymbolFlags.Variable, /*nodeNotFoundErrorMessage*/ undefined, /*nameArg*/ undefined, /*isUse*/ false); @@ -39509,7 +39487,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return; } // For a commonjs `const x = require`, validate the alias and exit - const symbol = getSymbolOfNode(node); + const symbol = getSymbolOfDeclaration(node); if (symbol.flags & SymbolFlags.Alias && isVariableDeclarationInitializedToBareOrAccessedRequire(node.kind === SyntaxKind.BindingElement ? node.parent.parent : node)) { checkAliasSymbol(node as BindingElement | VariableDeclaration); return; @@ -40986,7 +40964,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // Only process instance properties with computed names here. Static properties cannot be in conflict with indexers, // and properties with literal names were already checked. if (!isStatic(member) && !hasBindableName(member)) { - const symbol = getSymbolOfNode(member); + const symbol = getSymbolOfDeclaration(member); checkIndexConstraintForProperty(type, symbol, getTypeOfExpression((member as DynamicNamedDeclaration).name.expression), getNonMissingTypeOfSymbol(symbol)); } } @@ -41010,7 +40988,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { name && name.kind === SyntaxKind.ComputedPropertyName ? declaration : undefined; const localPropDeclaration = getParentOfSymbol(prop) === type.symbol ? declaration : undefined; for (const info of indexInfos) { - const localIndexDeclaration = info.declaration && getParentOfSymbol(getSymbolOfNode(info.declaration)) === type.symbol ? info.declaration : undefined; + const localIndexDeclaration = info.declaration && getParentOfSymbol(getSymbolOfDeclaration(info.declaration)) === type.symbol ? info.declaration : undefined; // We check only when (a) the property is declared in the containing type, or (b) the applicable index signature is declared // in the containing type, or (c) the containing type is an interface and no base interface contains both the property and // the index signature (i.e. property and index signature are declared in separate inherited interfaces). @@ -41031,10 +41009,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const declaration = checkInfo.declaration; const indexInfos = getApplicableIndexInfos(type, checkInfo.keyType); const interfaceDeclaration = getObjectFlags(type) & ObjectFlags.Interface ? getDeclarationOfKind(type.symbol, SyntaxKind.InterfaceDeclaration) : undefined; - const localCheckDeclaration = declaration && getParentOfSymbol(getSymbolOfNode(declaration)) === type.symbol ? declaration : undefined; + const localCheckDeclaration = declaration && getParentOfSymbol(getSymbolOfDeclaration(declaration)) === type.symbol ? declaration : undefined; for (const info of indexInfos) { if (info === checkInfo) continue; - const localIndexDeclaration = info.declaration && getParentOfSymbol(getSymbolOfNode(info.declaration)) === type.symbol ? info.declaration : undefined; + const localIndexDeclaration = info.declaration && getParentOfSymbol(getSymbolOfDeclaration(info.declaration)) === type.symbol ? info.declaration : undefined; // We check only when (a) the check index signature is declared in the containing type, or (b) the applicable index // signature is declared in the containing type, or (c) the containing type is an interface and no base interface contains // both index signatures (i.e. the index signatures are declared in separate inherited interfaces). @@ -41159,7 +41137,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const type = getTypeFromTypeReference(node as TypeReferenceNode); if (type.flags & TypeFlags.TypeParameter) { for (let i = index; i < typeParameters.length; i++) { - if (type.symbol === getSymbolOfNode(typeParameters[i])) { + if (type.symbol === getSymbolOfDeclaration(typeParameters[i])) { error(node, Diagnostics.Type_parameter_defaults_can_only_reference_previously_declared_type_parameters); } } @@ -41243,7 +41221,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { function checkClassExpression(node: ClassExpression): Type { checkClassLikeDeclaration(node); checkNodeDeferred(node); - return getTypeOfSymbol(getSymbolOfNode(node)); + return getTypeOfSymbol(getSymbolOfDeclaration(node)); } function checkClassExpressionDeferred(node: ClassExpression) { @@ -41271,7 +41249,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { checkCollisionsForDeclarationName(node, node.name); checkTypeParameters(getEffectiveTypeParameterDeclarations(node)); checkExportsOnMergedDeclarations(node); - const symbol = getSymbolOfNode(node); + const symbol = getSymbolOfDeclaration(node); const type = getDeclaredTypeOfSymbol(symbol) as InterfaceType; const typeWithThis = getTypeWithThisArgument(type); const staticType = getTypeOfSymbol(symbol) as ObjectType; @@ -41616,7 +41594,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return MemberOverrideStatus.Ok; } - const symbol = getSymbolOfNode(node); + const symbol = getSymbolOfDeclaration(node); const type = getDeclaredTypeOfSymbol(symbol) as InterfaceType; const typeWithThis = getTypeWithThisArgument(type); const staticType = getTypeOfSymbol(symbol) as ObjectType; @@ -41878,7 +41856,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (!isStatic(member) && isPropertyWithoutInitializer(member)) { const propName = (member as PropertyDeclaration).name; if (isIdentifier(propName) || isPrivateIdentifier(propName) || isComputedPropertyName(propName)) { - const type = getTypeOfSymbol(getSymbolOfNode(member)); + const type = getTypeOfSymbol(getSymbolOfDeclaration(member)); if (!(type.flags & TypeFlags.AnyOrUnknown || containsUndefinedType(type))) { if (!constructor || !isPropertyInitializedInConstructor(propName, type, constructor)) { error(member.name, Diagnostics.Property_0_has_no_initializer_and_is_not_definitely_assigned_in_the_constructor, declarationNameToString(propName)); @@ -41934,7 +41912,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { checkTypeNameIsReserved(node.name, Diagnostics.Interface_name_cannot_be_0); checkExportsOnMergedDeclarations(node); - const symbol = getSymbolOfNode(node); + const symbol = getSymbolOfDeclaration(node); checkTypeParameterListsIdentical(symbol); // Only check this symbol once @@ -42180,7 +42158,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // for the first member. // // Only perform this check once per symbol - const enumSymbol = getSymbolOfNode(node); + const enumSymbol = getSymbolOfDeclaration(node); const firstDeclaration = getDeclarationOfKind(enumSymbol, node.kind); if (node === firstDeclaration) { if (enumSymbol.declarations && enumSymbol.declarations.length > 1) { @@ -42293,7 +42271,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } checkExportsOnMergedDeclarations(node); - const symbol = getSymbolOfNode(node); + const symbol = getSymbolOfDeclaration(node); // The following checks only apply on a non-ambient instantiated module declaration. if (symbol.flags & SymbolFlags.ValueModule @@ -42327,7 +42305,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // We can detect if augmentation was applied using following rules: // - augmentation for a global scope is always applied // - augmentation for some external module is applied if symbol for augmentation is merged (it was combined with target module). - const checkBody = isGlobalAugmentation || (getSymbolOfNode(node).flags & SymbolFlags.Transient); + const checkBody = isGlobalAugmentation || (getSymbolOfDeclaration(node).flags & SymbolFlags.Transient); if (checkBody && node.body) { for (const statement of node.body.statements) { checkModuleAugmentationElement(statement, isGlobalAugmentation); @@ -42459,7 +42437,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } function checkAliasSymbol(node: ImportEqualsDeclaration | VariableDeclaration | ImportClause | NamespaceImport | ImportSpecifier | ExportSpecifier | NamespaceExport | BindingElement) { - let symbol = getSymbolOfNode(node); + let symbol = getSymbolOfDeclaration(node); const target = resolveAlias(symbol); if (target !== unknownSymbol) { @@ -42698,7 +42676,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { markExportAsReferenced(node); } if (node.moduleReference.kind !== SyntaxKind.ExternalModuleReference) { - const target = resolveAlias(getSymbolOfNode(node)); + const target = resolveAlias(getSymbolOfDeclaration(node)); if (target !== unknownSymbol) { const targetFlags = getAllSymbolFlags(target); if (targetFlags & SymbolFlags.Value) { @@ -42803,13 +42781,13 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { function importClauseContainsReferencedImport(importClause: ImportClause) { return forEachImportClauseDeclaration(importClause, declaration => { - return !!getSymbolOfNode(declaration).isReferenced; + return !!getSymbolOfDeclaration(declaration).isReferenced; }); } function importClauseContainsConstEnumUsedAsValue(importClause: ImportClause) { return forEachImportClauseDeclaration(importClause, declaration => { - return !!getSymbolLinks(getSymbolOfNode(declaration)).constEnumReferenced; + return !!getSymbolLinks(getSymbolOfDeclaration(declaration)).constEnumReferenced; }); } @@ -42826,9 +42804,9 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return isImportEqualsDeclaration(statement) && isExternalModuleReference(statement.moduleReference) && !statement.isTypeOnly && - getSymbolOfNode(statement).isReferenced && + getSymbolOfDeclaration(statement).isReferenced && !isReferencedAliasDeclaration(statement, /*checkChildren*/ false) && - !getSymbolLinks(getSymbolOfNode(statement)).constEnumReferenced; + !getSymbolLinks(getSymbolOfDeclaration(statement)).constEnumReferenced; } function checkImportsForTypeOnlyConversion(sourceFile: SourceFile) { @@ -42951,7 +42929,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } function checkExternalModuleExports(node: SourceFile | ModuleDeclaration) { - const moduleSymbol = getSymbolOfNode(node); + const moduleSymbol = getSymbolOfDeclaration(node); const links = getSymbolLinks(moduleSymbol); if (!links.exportsChecked) { const exportEqualsSymbol = moduleSymbol.exports!.get("export=" as __String); @@ -43011,15 +42989,17 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } function checkSourceElementWorker(node: Node): void { - forEach((node as JSDocContainer).jsDoc, ({ comment, tags }) => { - checkJSDocCommentWorker(comment); - forEach(tags, tag => { - checkJSDocCommentWorker(tag.comment); - if (isInJSFile(node)) { - checkSourceElement(tag); - } + if (canHaveJSDoc(node)) { + forEach(node.jsDoc, ({ comment, tags }) => { + checkJSDocCommentWorker(comment); + forEach(tags, tag => { + checkJSDocCommentWorker(tag.comment); + if (isInJSFile(node)) { + checkSourceElement(tag); + } + }); }); - }); + } const kind = node.kind; if (cancellationToken) { @@ -43033,7 +43013,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { cancellationToken.throwIfCancellationRequested(); } } - if (kind >= SyntaxKind.FirstStatement && kind <= SyntaxKind.LastStatement && node.flowNode && !isReachableFlowNode(node.flowNode)) { + if (kind >= SyntaxKind.FirstStatement && kind <= SyntaxKind.LastStatement && canHaveFlowNode(node) && node.flowNode && !isReachableFlowNode(node.flowNode)) { errorOrSuggestion(compilerOptions.allowUnreachableCode === false, node, Diagnostics.Unreachable_code_detected); } @@ -43550,7 +43530,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { function populateSymbols() { while (location) { - if (location.locals && !isGlobalSourceFile(location)) { + if (canHaveLocals(location) && location.locals && !isGlobalSourceFile(location)) { copySymbols(location.locals, meaning); } @@ -43559,15 +43539,15 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (!isExternalModule(location as SourceFile)) break; // falls through case SyntaxKind.ModuleDeclaration: - copyLocallyVisibleExportSymbols(getSymbolOfNode(location as ModuleDeclaration | SourceFile).exports!, meaning & SymbolFlags.ModuleMember); + copyLocallyVisibleExportSymbols(getSymbolOfDeclaration(location as ModuleDeclaration | SourceFile).exports!, meaning & SymbolFlags.ModuleMember); break; case SyntaxKind.EnumDeclaration: - copySymbols(getSymbolOfNode(location as EnumDeclaration).exports!, meaning & SymbolFlags.EnumMember); + copySymbols(getSymbolOfDeclaration(location as EnumDeclaration).exports!, meaning & SymbolFlags.EnumMember); break; case SyntaxKind.ClassExpression: const className = (location as ClassExpression).name; if (className) { - copySymbol(location.symbol, meaning); + copySymbol((location as ClassExpression).symbol, meaning); } // this fall-through is necessary because we would like to handle @@ -43580,13 +43560,13 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // (type parameters of classDeclaration/classExpression and interface are in member property of the symbol. // Note: that the memberFlags come from previous iteration. if (!isStaticSymbol) { - copySymbols(getMembersOfSymbol(getSymbolOfNode(location as ClassDeclaration | InterfaceDeclaration)), meaning & SymbolFlags.Type); + copySymbols(getMembersOfSymbol(getSymbolOfDeclaration(location as ClassDeclaration | InterfaceDeclaration)), meaning & SymbolFlags.Type); } break; case SyntaxKind.FunctionExpression: const funcName = (location as FunctionExpression).name; if (funcName) { - copySymbol(location.symbol, meaning); + copySymbol((location as FunctionExpression).symbol, meaning); } break; } @@ -43664,13 +43644,12 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return node.parent.kind === SyntaxKind.ExpressionWithTypeArguments; } - function forEachEnclosingClass(node: Node, callback: (node: Node) => T | undefined): T | undefined { + function forEachEnclosingClass(node: Node, callback: (node: ClassLikeDeclaration) => T | undefined): T | undefined { let result: T | undefined; - - while (true) { - node = getContainingClass(node)!; - if (!node) break; - if (result = callback(node)) break; + let containingClass = getContainingClass(node); + while (containingClass) { + if (result = callback(containingClass)) break; + containingClass = getContainingClass(containingClass); } return result; @@ -43722,7 +43701,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { case AssignmentDeclarationKind.ThisProperty: case AssignmentDeclarationKind.ModuleExports: case AssignmentDeclarationKind.Property: - return getSymbolOfNode(entityName.parent.parent); + return getSymbolOfDeclaration(entityName.parent.parent as BinaryExpression); } } @@ -43832,7 +43811,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (!result && isJSDoc) { const container = findAncestor(name, or(isClassLike, isInterfaceDeclaration)); if (container) { - return resolveJSDocMemberName(name, /*ignoreErrors*/ false, getSymbolOfNode(container)); + return resolveJSDocMemberName(name, /*ignoreErrors*/ false, getSymbolOfDeclaration(container)); } } if (result && isJSDoc) { @@ -43938,8 +43917,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } function getSymbolAtLocation(node: Node, ignoreErrors?: boolean): Symbol | undefined { - if (node.kind === SyntaxKind.SourceFile) { - return isExternalModule(node as SourceFile) ? getMergedSymbol(node.symbol) : undefined; + if (isSourceFile(node)) { + return isExternalModule(node) ? getMergedSymbol(node.symbol) : undefined; } const { parent } = node; const grandParent = parent.parent; @@ -43951,13 +43930,13 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (isDeclarationNameOrImportPropertyName(node)) { // This is a declaration, call getSymbolOfNode - const parentSymbol = getSymbolOfNode(parent)!; + const parentSymbol = getSymbolOfDeclaration(parent as Declaration)!; return isImportOrExportSpecifier(node.parent) && node.parent.propertyName === node ? getImmediateAliasedSymbol(parentSymbol) : parentSymbol; } else if (isLiteralComputedPropertyDeclarationName(node)) { - return getSymbolOfNode(parent.parent); + return getSymbolOfDeclaration(parent.parent as Declaration); } if (node.kind === SyntaxKind.Identifier) { @@ -44002,7 +43981,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // falls through case SyntaxKind.ThisKeyword: - const container = getThisContainer(node, /*includeArrowFunctions*/ false); + const container = getThisContainer(node, /*includeArrowFunctions*/ false, /*includeClassComputedPropertyName*/ false); if (isFunctionLike(container)) { const sig = getSignatureFromDeclaration(container); if (sig.thisParameter) { @@ -44042,7 +44021,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return resolveExternalModuleName(node, node as LiteralExpression, ignoreErrors); } if (isCallExpression(parent) && isBindableObjectDefinePropertyCall(parent) && parent.arguments[1] === node) { - return getSymbolOfNode(parent); + return getSymbolOfDeclaration(parent); } // falls through @@ -44117,7 +44096,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } const classDecl = tryGetClassImplementingOrExtendingExpressionWithTypeArguments(node); - const classType = classDecl && getDeclaredTypeOfClassOrInterface(getSymbolOfNode(classDecl.class)); + const classType = classDecl && getDeclaredTypeOfClassOrInterface(getSymbolOfDeclaration(classDecl.class)); if (isPartOfTypeNode(node)) { const typeFromTypeNode = getTypeFromTypeNode(node as TypeNode); return classType ? getTypeWithThisArgument(typeFromTypeNode, classType.thisType) : typeFromTypeNode; @@ -44136,7 +44115,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (isTypeDeclaration(node)) { // In this case, we call getSymbolOfNode instead of getSymbolAtLocation because it is a declaration - const symbol = getSymbolOfNode(node); + const symbol = getSymbolOfDeclaration(node); return getDeclaredTypeOfSymbol(symbol); } @@ -44147,7 +44126,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (isDeclaration(node)) { // In this case, we call getSymbolOfNode instead of getSymbolAtLocation because it is a declaration - const symbol = getSymbolOfNode(node); + const symbol = getSymbolOfDeclaration(node); return symbol ? getTypeOfSymbol(symbol) : errorType; } @@ -44386,7 +44365,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const symbolIsUmdExport = symbolFile !== referenceFile; return symbolIsUmdExport ? undefined : symbolFile; } - return findAncestor(node.parent, (n): n is ModuleDeclaration | EnumDeclaration => isModuleOrEnumDeclaration(n) && getSymbolOfNode(n) === parentSymbol); + return findAncestor(node.parent, (n): n is ModuleDeclaration | EnumDeclaration => isModuleOrEnumDeclaration(n) && getSymbolOfDeclaration(n) === parentSymbol); } } } @@ -44483,7 +44462,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { function isDeclarationWithCollidingName(nodeIn: Declaration): boolean { const node = getParseTreeNode(nodeIn, isDeclaration); if (node) { - const symbol = getSymbolOfNode(node); + const symbol = getSymbolOfDeclaration(node); if (symbol) { return isSymbolOfDeclarationWithCollidingName(symbol); } @@ -44495,12 +44474,12 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { function isValueAliasDeclaration(node: Node): boolean { switch (node.kind) { case SyntaxKind.ImportEqualsDeclaration: - return isAliasResolvedToValue(getSymbolOfNode(node)); + return isAliasResolvedToValue(getSymbolOfDeclaration(node as ImportEqualsDeclaration)); case SyntaxKind.ImportClause: case SyntaxKind.NamespaceImport: case SyntaxKind.ImportSpecifier: case SyntaxKind.ExportSpecifier: - const symbol = getSymbolOfNode(node); + const symbol = getSymbolOfDeclaration(node as ImportClause | NamespaceImport | ImportSpecifier | ExportSpecifier); return !!symbol && isAliasResolvedToValue(symbol) && !getTypeOnlyAliasDeclaration(symbol, SymbolFlags.Value); case SyntaxKind.ExportDeclaration: const exportClause = (node as ExportDeclaration).exportClause; @@ -44510,7 +44489,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { ); case SyntaxKind.ExportAssignment: return (node as ExportAssignment).expression && (node as ExportAssignment).expression.kind === SyntaxKind.Identifier ? - isAliasResolvedToValue(getSymbolOfNode(node)) : + isAliasResolvedToValue(getSymbolOfDeclaration(node as ExportAssignment)) : true; } return false; @@ -44523,7 +44502,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return false; } - const isValue = isAliasResolvedToValue(getSymbolOfNode(node)); + const isValue = isAliasResolvedToValue(getSymbolOfDeclaration(node)); return isValue && node.moduleReference && !nodeIsMissing(node.moduleReference); } @@ -44547,12 +44526,12 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { function isReferencedAliasDeclaration(node: Node, checkChildren?: boolean): boolean { if (isAliasSymbolDeclaration(node)) { - const symbol = getSymbolOfNode(node); + const symbol = getSymbolOfDeclaration(node as Declaration); const links = symbol && getSymbolLinks(symbol); if (links?.referenced) { return true; } - const target = getSymbolLinks(symbol!).aliasTarget; // TODO: GH#18217 + const target = getSymbolLinks(symbol).aliasTarget; if (target && getEffectiveModifierFlags(node) & ModifierFlags.Export && getAllSymbolFlags(target) & SymbolFlags.Value && (shouldPreserveConstEnums(compilerOptions) || !isConstEnumOrConstEnumOnlyModule(target))) { @@ -44570,7 +44549,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { function isImplementationOfOverload(node: SignatureDeclaration) { if (nodeIsPresent((node as FunctionLikeDeclaration).body)) { if (isGetAccessor(node) || isSetAccessor(node)) return false; // Get or set accessors can never be overload implementations, but can have up to 2 signatures - const symbol = getSymbolOfNode(node); + const symbol = getSymbolOfDeclaration(node); const signaturesOfSymbol = getSignaturesOfSymbol(symbol); // If this function body corresponds to function with multiple signature, it is implementation of overload // e.g.: function foo(a: string): string; @@ -44609,7 +44588,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (!declaration) { return false; } - const symbol = getSymbolOfNode(declaration); + const symbol = getSymbolOfDeclaration(declaration); if (!symbol || !(symbol.flags & SymbolFlags.Function)) { return false; } @@ -44621,7 +44600,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (!declaration) { return emptyArray; } - const symbol = getSymbolOfNode(declaration); + const symbol = getSymbolOfDeclaration(declaration); return symbol && getPropertiesOfType(getTypeOfSymbol(symbol)) || emptyArray; } @@ -44750,7 +44729,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return factory.createToken(SyntaxKind.AnyKeyword) as KeywordTypeNode; } // Get type of the symbol if this is the valid symbol otherwise get type at location - const symbol = getSymbolOfNode(declaration); + const symbol = getSymbolOfDeclaration(declaration); let type = symbol && !(symbol.flags & (SymbolFlags.TypeLiteral | SymbolFlags.Signature)) ? getWidenedLiteralType(getTypeOfSymbol(symbol)) : errorType; @@ -44845,7 +44824,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { function isLiteralConstDeclaration(node: VariableDeclaration | PropertyDeclaration | PropertySignature | ParameterDeclaration): boolean { if (isDeclarationReadonly(node) || isVariableDeclaration(node) && isVarConst(node)) { - return isFreshLiteralType(getTypeOfSymbol(getSymbolOfNode(node))); + return isFreshLiteralType(getTypeOfSymbol(getSymbolOfDeclaration(node))); } return false; } @@ -44861,7 +44840,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } function createLiteralConstValue(node: VariableDeclaration | PropertyDeclaration | PropertySignature | ParameterDeclaration, tracker: SymbolTracker) { - const type = getTypeOfSymbol(getSymbolOfNode(node)); + const type = getTypeOfSymbol(getSymbolOfDeclaration(node)); return literalTypeToNode(type as FreshableType, node, tracker); } @@ -44963,7 +44942,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { isLiteralConstDeclaration, isLateBound: (nodeIn: Declaration): nodeIn is LateBoundDeclaration => { const node = getParseTreeNode(nodeIn, isDeclaration); - const symbol = node && getSymbolOfNode(node); + const symbol = node && getSymbolOfDeclaration(node); return !!(symbol && getCheckFlags(symbol) & CheckFlags.Late); }, getJsxFactoryEntity, @@ -44971,7 +44950,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { getAllAccessorDeclarations(accessor: AccessorDeclaration): AllAccessorDeclarations { accessor = getParseTreeNode(accessor, isGetOrSetAccessorDeclaration)!; // TODO: GH#18217 const otherKind = accessor.kind === SyntaxKind.SetAccessor ? SyntaxKind.GetAccessor : SyntaxKind.SetAccessor; - const otherAccessor = getDeclarationOfKind(getSymbolOfNode(accessor), otherKind); + const otherAccessor = getDeclarationOfKind(getSymbolOfDeclaration(accessor), otherKind); const firstAccessor = otherAccessor && (otherAccessor.pos < accessor.pos) ? otherAccessor : accessor; const secondAccessor = otherAccessor && (otherAccessor.pos < accessor.pos) ? accessor : otherAccessor; const setAccessor = accessor.kind === SyntaxKind.SetAccessor ? accessor : otherAccessor as SetAccessorDeclaration; @@ -44992,7 +44971,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { getDeclarationStatementsForSourceFile: (node, flags, tracker, bundled) => { const n = getParseTreeNode(node) as SourceFile; Debug.assert(n && n.kind === SyntaxKind.SourceFile, "Non-sourcefile node passed into getDeclarationsForSourceFile"); - const sym = getSymbolOfNode(node); + const sym = getSymbolOfDeclaration(node); if (!sym) { return !node.locals ? [] : nodeBuilder.symbolTableToDeclarationStatements(node.locals, node, flags, tracker, bundled); } @@ -46786,9 +46765,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { function checkGrammarProperty(node: PropertyDeclaration | PropertySignature) { if (isComputedPropertyName(node.name) && isBinaryExpression(node.name.expression) && node.name.expression.operatorToken.kind === SyntaxKind.InKeyword) { - return grammarErrorOnNode( - (node.parent as ClassLikeDeclaration | InterfaceDeclaration | TypeLiteralNode).members[0], - Diagnostics.A_mapped_type_may_not_declare_properties_or_methods); + return grammarErrorOnNode(node.parent.members[0], Diagnostics.A_mapped_type_may_not_declare_properties_or_methods); } if (isClassLike(node.parent)) { if (isStringLiteral(node.name) && node.name.text === "constructor") { @@ -47196,3 +47173,152 @@ export function signatureHasRestParameter(s: Signature) { export function signatureHasLiteralTypes(s: Signature) { return !!(s.flags & SignatureFlags.HasLiteralTypes); } + +function createBasicNodeBuilderModuleSpecifierResolutionHost(host: TypeCheckerHost): ModuleSpecifierResolutionHost & { getCommonSourceDirectory(): string } { + return { + getCommonSourceDirectory: !!(host as Program).getCommonSourceDirectory ? () => (host as Program).getCommonSourceDirectory() : () => "", + getCurrentDirectory: () => host.getCurrentDirectory(), + getSymlinkCache: maybeBind(host, host.getSymlinkCache), + getPackageJsonInfoCache: () => host.getPackageJsonInfoCache?.(), + useCaseSensitiveFileNames: maybeBind(host, host.useCaseSensitiveFileNames), + redirectTargetsMap: host.redirectTargetsMap, + getProjectReferenceRedirect: fileName => host.getProjectReferenceRedirect(fileName), + isSourceOfProjectReferenceRedirect: fileName => host.isSourceOfProjectReferenceRedirect(fileName), + fileExists: fileName => host.fileExists(fileName), + getFileIncludeReasons: () => host.getFileIncludeReasons(), + readFile: host.readFile ? (fileName => host.readFile!(fileName)) : undefined, + }; +} + +interface NodeBuilderContext { + enclosingDeclaration: Node | undefined; + flags: NodeBuilderFlags; + tracker: SymbolTrackerImpl; + + // State + encounteredError: boolean; + reportedDiagnostic: boolean; + visitedTypes: Set | undefined; + symbolDepth: Map | undefined; + inferTypeParameters: TypeParameter[] | undefined; + approximateLength: number; + truncating?: boolean; + typeParameterSymbolList?: Set; + typeParameterNames?: Map; + typeParameterNamesByText?: Set; + typeParameterNamesByTextNextNameCount?: Map; + usedSymbolNames?: Set; + remappedSymbolNames?: Map; + reverseMappedStack?: ReverseMappedSymbol[]; +} + +class SymbolTrackerImpl implements SymbolTracker { + moduleResolverHost: ModuleSpecifierResolutionHost & { getCommonSourceDirectory(): string } | undefined = undefined; + context: NodeBuilderContext; + + readonly inner: SymbolTracker | undefined = undefined; + readonly canTrackSymbol: boolean; + disableTrackSymbol = false; + + constructor(context: NodeBuilderContext, tracker: SymbolTracker | undefined, moduleResolverHost: ModuleSpecifierResolutionHost & { getCommonSourceDirectory(): string } | undefined) { + while (tracker instanceof SymbolTrackerImpl) { + tracker = tracker.inner; + } + + this.inner = tracker; + this.moduleResolverHost = moduleResolverHost; + this.context = context; + this.canTrackSymbol = !!this.inner?.trackSymbol; + } + + trackSymbol(symbol: Symbol, enclosingDeclaration: Node | undefined, meaning: SymbolFlags): boolean { + if (this.inner?.trackSymbol && !this.disableTrackSymbol) { + if (this.inner.trackSymbol(symbol, enclosingDeclaration, meaning)) { + this.onDiagnosticReported(); + return true; + } + } + return false; + } + + reportInaccessibleThisError(): void { + if (this.inner?.reportInaccessibleThisError) { + this.onDiagnosticReported(); + this.inner.reportInaccessibleThisError(); + } + } + + reportPrivateInBaseOfClassExpression(propertyName: string): void { + if (this.inner?.reportPrivateInBaseOfClassExpression) { + this.onDiagnosticReported(); + this.inner.reportPrivateInBaseOfClassExpression(propertyName); + } + } + + reportInaccessibleUniqueSymbolError(): void { + if (this.inner?.reportInaccessibleUniqueSymbolError) { + this.onDiagnosticReported(); + this.inner.reportInaccessibleUniqueSymbolError(); + } + } + + reportCyclicStructureError(): void { + if (this.inner?.reportCyclicStructureError) { + this.onDiagnosticReported(); + this.inner.reportCyclicStructureError(); + } + } + + reportLikelyUnsafeImportRequiredError(specifier: string): void { + if (this.inner?.reportLikelyUnsafeImportRequiredError) { + this.onDiagnosticReported(); + this.inner.reportLikelyUnsafeImportRequiredError(specifier); + } + } + + reportTruncationError(): void { + if (this.inner?.reportTruncationError) { + this.onDiagnosticReported(); + this.inner.reportTruncationError(); + } + } + + trackReferencedAmbientModule(decl: ModuleDeclaration, symbol: Symbol): void { + if (this.inner?.trackReferencedAmbientModule) { + this.onDiagnosticReported(); + this.inner.trackReferencedAmbientModule(decl, symbol); + } + } + + trackExternalModuleSymbolOfImportTypeNode(symbol: Symbol): void { + if (this.inner?.trackExternalModuleSymbolOfImportTypeNode) { + this.onDiagnosticReported(); + this.inner.trackExternalModuleSymbolOfImportTypeNode(symbol); + } + } + + reportNonlocalAugmentation(containingFile: SourceFile, parentSymbol: Symbol, augmentingSymbol: Symbol): void { + if (this.inner?.reportNonlocalAugmentation) { + this.onDiagnosticReported(); + this.inner.reportNonlocalAugmentation(containingFile, parentSymbol, augmentingSymbol); + } + } + + reportNonSerializableProperty(propertyName: string): void { + if (this.inner?.reportNonSerializableProperty) { + this.onDiagnosticReported(); + this.inner.reportNonSerializableProperty(propertyName); + } + } + + reportImportTypeNodeResolutionModeOverride(): void { + if (this.inner?.reportImportTypeNodeResolutionModeOverride) { + this.onDiagnosticReported(); + this.inner.reportImportTypeNodeResolutionModeOverride(); + } + } + + private onDiagnosticReported() { + this.context.reportedDiagnostic = true; + } +} \ No newline at end of file diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index 447da12e438f8..3c63eec2353bb 100644 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -28,6 +28,7 @@ import { BundleFileTextLikeKind, CallExpression, CallSignatureDeclaration, + canHaveLocals, CaseBlock, CaseClause, CaseOrDefaultClause, @@ -181,6 +182,7 @@ import { getTransformers, getTypeNode, guessIndentation, + HasLocals, hasRecordedExternalHelpers, HeritageClause, Identifier, @@ -412,6 +414,7 @@ import { tracing, TransformationResult, transformNodes, + tryCast, tryParseRawSourceMap, TryStatement, TupleTypeNode, @@ -2475,8 +2478,7 @@ export function createPrinter(printerOptions: PrinterOptions = {}, handlers: Pri // function emitPrivateIdentifier(node: PrivateIdentifier) { - const writeText = node.symbol ? writeSymbol : write; - writeText(getTextOfNode(node, /*includeTrivia*/ false), node.symbol); + write(getTextOfNode(node, /*includeTrivia*/ false)); } @@ -5656,9 +5658,9 @@ export function createPrinter(printerOptions: PrinterOptions = {}, handlers: Pri /** * 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) { + function isUniqueLocalName(name: string, container: HasLocals | undefined): boolean { + for (let node = container; node && isNodeDescendantOf(node, container); node = node.nextContainer) { + if (canHaveLocals(node) && node.locals) { const local = node.locals.get(escapeLeadingUnderscores(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)) { @@ -5798,7 +5800,7 @@ export function createPrinter(printerOptions: PrinterOptions = {}, handlers: Pri 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, isUniqueName, /*optimistic*/ false, /*scoped*/ false, /*privateName*/ false, /*prefix*/ "", /*suffix*/ ""); + return isUniqueLocalName(name, tryCast(node, canHaveLocals)) ? name : makeUniqueName(name, isUniqueName, /*optimistic*/ false, /*scoped*/ false, /*privateName*/ false, /*prefix*/ "", /*suffix*/ ""); } /** diff --git a/src/compiler/factory/nodeFactory.ts b/src/compiler/factory/nodeFactory.ts index bfe41875a84c8..3dce5667968b3 100644 --- a/src/compiler/factory/nodeFactory.ts +++ b/src/compiler/factory/nodeFactory.ts @@ -1,4 +1,5 @@ import { + __String, addRange, append, appendIfUnique, @@ -37,7 +38,6 @@ import { CallChain, CallExpression, CallSignatureDeclaration, - canHaveModifiers, CaseBlock, CaseClause, CaseOrDefaultClause, @@ -46,7 +46,6 @@ import { ClassDeclaration, ClassElement, ClassExpression, - ClassLikeDeclaration, ClassStaticBlockDeclaration, ColonToken, CommaListExpression, @@ -106,11 +105,11 @@ import { ForStatement, FunctionDeclaration, FunctionExpression, - FunctionLikeDeclaration, FunctionTypeNode, GeneratedIdentifier, GeneratedIdentifierFlags, GeneratedNamePart, + GeneratedPrivateIdentifier, GetAccessorDeclaration, getAllUnscopedEmitHelpers, getBuildInfo, @@ -129,7 +128,6 @@ import { hasInvalidEscape, HasModifiers, hasProperty, - hasStaticModifier, hasSyntacticModifier, HeritageClause, Identifier, @@ -171,6 +169,7 @@ import { isFunctionDeclaration, isFunctionExpression, isGeneratedIdentifier, + isGeneratedPrivateIdentifier, isGetAccessorDeclaration, isHoistedFunction, isHoistedVariableStatement, @@ -292,6 +291,7 @@ import { LiteralTypeNode, map, MappedTypeNode, + MemberName, memoize, memoizeOne, MergeDeclarationMarker, @@ -314,7 +314,6 @@ import { ModuleReference, Mutable, MutableNodeArray, - NamedDeclaration, NamedExportBindings, NamedExports, NamedImportBindings, @@ -350,6 +349,7 @@ import { ParenthesizedTypeNode, parseNodeFactory, PartiallyEmittedExpression, + Path, PlusToken, PostfixUnaryExpression, PostfixUnaryOperator, @@ -375,6 +375,7 @@ import { QuestionDotToken, QuestionToken, ReadonlyKeyword, + RedirectInfo, reduceLeft, RegularExpressionLiteral, RestTypeNode, @@ -390,7 +391,6 @@ import { setEmitFlags, setParent, setTextRange, - setTextRangePosEnd, setTextRangePosWidth, ShorthandPropertyAssignment, SignatureDeclarationBase, @@ -406,7 +406,6 @@ import { startsWith, Statement, StringLiteral, - StringLiteralLike, stringToToken, SuperExpression, SwitchStatement, @@ -854,8 +853,6 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode get updateJSDocReturnTag() { return getJSDocTypeLikeTagUpdateFunction(SyntaxKind.JSDocReturnTag); }, get createJSDocThisTag() { return getJSDocTypeLikeTagCreateFunction(SyntaxKind.JSDocThisTag); }, get updateJSDocThisTag() { return getJSDocTypeLikeTagUpdateFunction(SyntaxKind.JSDocThisTag); }, - get createJSDocEnumTag() { return getJSDocTypeLikeTagCreateFunction(SyntaxKind.JSDocEnumTag); }, - get updateJSDocEnumTag() { return getJSDocTypeLikeTagUpdateFunction(SyntaxKind.JSDocEnumTag); }, get createJSDocAuthorTag() { return getJSDocSimpleTagCreateFunction(SyntaxKind.JSDocAuthorTag); }, get updateJSDocAuthorTag() { return getJSDocSimpleTagUpdateFunction(SyntaxKind.JSDocAuthorTag); }, get createJSDocClassTag() { return getJSDocSimpleTagCreateFunction(SyntaxKind.JSDocClassTag); }, @@ -874,6 +871,8 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode get updateJSDocDeprecatedTag() { return getJSDocSimpleTagUpdateFunction(SyntaxKind.JSDocDeprecatedTag); }, get createJSDocThrowsTag() { return getJSDocTypeLikeTagCreateFunction(SyntaxKind.JSDocThrowsTag); }, get updateJSDocThrowsTag() { return getJSDocTypeLikeTagUpdateFunction(SyntaxKind.JSDocThrowsTag); }, + createJSDocEnumTag, + updateJSDocEnumTag, createJSDocUnknownTag, updateJSDocUnknownTag, createJSDocText, @@ -920,6 +919,7 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode updateEnumMember, createSourceFile, updateSourceFile, + createRedirectedSourceFile, createBundle, updateBundle, createUnparsedSource, @@ -1052,8 +1052,10 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode // small arrays (1 to 4 elements) to give the VM a chance to allocate an optimal representation. const length = elements.length; const array = (length >= 1 && length <= 4 ? elements.slice() : elements) as MutableNodeArray; - setTextRangePosEnd(array, -1, -1); + array.pos = -1; + array.end = -1; array.hasTrailingComma = !!hasTrailingComma; + array.transformFlags = TransformFlags.None; aggregateChildrenFlags(array); Debug.attachNodeArrayDebugInfo(array); return array; @@ -1063,96 +1065,10 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode return baseFactory.createBaseNode(kind) as Mutable; } - function createBaseDeclaration( - kind: T["kind"], - ) { + function createBaseDeclaration(kind: T["kind"]) { const node = createBaseNode(kind); - // NOTE: The following properties are commonly set by the binder and are added here to - // ensure declarations have a stable shape. node.symbol = undefined!; // initialized by binder node.localSymbol = undefined; // initialized by binder - node.locals = undefined; // initialized by binder - node.nextContainer = undefined; // initialized by binder - return node; - } - - function createBaseNamedDeclaration( - kind: T["kind"], - modifiers: readonly ModifierLike[] | undefined, - name: Identifier | PrivateIdentifier | StringLiteralLike | NumericLiteral | ComputedPropertyName | BindingPattern | string | undefined - ) { - const node = createBaseDeclaration(kind); - name = asName(name); - node.name = name; - if (canHaveModifiers(node)) { - (node as Mutable).modifiers = asNodeArray(modifiers); - (node as Mutable).transformFlags |= propagateChildrenFlags(node.modifiers); - // node.decorators = filter(node.modifiers, isDecorator); - } - - // The PropertyName of a member is allowed to be `await`. - // We don't need to exclude `await` for type signatures since types - // don't propagate child flags. - if (name) { - switch (node.kind) { - case SyntaxKind.MethodDeclaration: - case SyntaxKind.GetAccessor: - case SyntaxKind.SetAccessor: - case SyntaxKind.PropertyDeclaration: - case SyntaxKind.PropertyAssignment: - if (isIdentifier(name)) { - node.transformFlags |= propagateIdentifierNameFlags(name); - break; - } - // fall through - default: - node.transformFlags |= propagateChildFlags(name); - break; - } - } - return node; - } - - function createBaseGenericNamedDeclaration }>( - kind: T["kind"], - modifiers: readonly ModifierLike[] | undefined, - name: Identifier | PrivateIdentifier | StringLiteralLike | NumericLiteral | ComputedPropertyName | BindingPattern | string | undefined, - typeParameters: readonly TypeParameterDeclaration[] | undefined - ) { - const node = createBaseNamedDeclaration( - kind, - modifiers, - name - ); - node.typeParameters = asNodeArray(typeParameters); - node.transformFlags |= propagateChildrenFlags(node.typeParameters); - if (typeParameters) node.transformFlags |= TransformFlags.ContainsTypeScript; - return node; - } - - function createBaseSignatureDeclaration( - kind: T["kind"], - modifiers: readonly ModifierLike[] | undefined, - name: Identifier | PrivateIdentifier | StringLiteralLike | NumericLiteral | ComputedPropertyName | BindingPattern | string | undefined, - typeParameters: readonly TypeParameterDeclaration[] | undefined, - parameters: readonly ParameterDeclaration[] | undefined, - type: TypeNode | undefined - ) { - const node = createBaseGenericNamedDeclaration( - kind, - modifiers, - name, - typeParameters - ); - node.parameters = createNodeArray(parameters); - node.type = type; - node.transformFlags |= - propagateChildrenFlags(node.parameters) | - propagateChildFlags(node.type); - if (type) node.transformFlags |= TransformFlags.ContainsTypeScript; - - // The following properties are used for quick info - node.typeArguments = undefined; return node; } @@ -1164,118 +1080,14 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode return update(updated, original); } - function createBaseFunctionLikeDeclaration( - kind: T["kind"], - modifiers: readonly ModifierLike[] | undefined, - name: Identifier | PrivateIdentifier | StringLiteralLike | NumericLiteral | ComputedPropertyName | BindingPattern | string | undefined, - typeParameters: readonly TypeParameterDeclaration[] | undefined, - parameters: readonly ParameterDeclaration[] | undefined, - type: TypeNode | undefined, - body: T["body"] - ) { - const node = createBaseSignatureDeclaration( - kind, - modifiers, - name, - typeParameters, - parameters, - type - ); - node.body = body; - node.transformFlags |= propagateChildFlags(node.body) & ~TransformFlags.ContainsPossibleTopLevelAwait; - if (!body) node.transformFlags |= TransformFlags.ContainsTypeScript; - return node; - } - - function createBaseInterfaceOrClassLikeDeclaration( - kind: T["kind"], - modifiers: readonly ModifierLike[] | undefined, - name: string | Identifier | undefined, - typeParameters: readonly TypeParameterDeclaration[] | undefined, - heritageClauses: readonly HeritageClause[] | undefined - ) { - const node = createBaseGenericNamedDeclaration( - kind, - modifiers, - name, - typeParameters - ); - node.heritageClauses = asNodeArray(heritageClauses); - node.transformFlags |= propagateChildrenFlags(node.heritageClauses); - return node; - } - - function createBaseClassLikeDeclaration( - kind: T["kind"], - modifiers: readonly ModifierLike[] | undefined, - name: string | Identifier | undefined, - typeParameters: readonly TypeParameterDeclaration[] | undefined, - heritageClauses: readonly HeritageClause[] | undefined, - members: readonly ClassElement[] - ) { - const node = createBaseInterfaceOrClassLikeDeclaration( - kind, - modifiers, - name, - typeParameters, - heritageClauses - ); - node.members = createNodeArray(members); - node.transformFlags |= propagateChildrenFlags(node.members); - return node; - } - - function createBaseBindingLikeDeclaration( - kind: T["kind"], - modifiers: readonly ModifierLike[] | undefined, - name: string | T["name"] | undefined, - initializer: Expression | undefined - ) { - const node = createBaseNamedDeclaration( - kind, - modifiers, - name - ); - node.initializer = initializer; - node.transformFlags |= propagateChildFlags(node.initializer); - return node; - } - - function createBaseVariableLikeDeclaration( - kind: T["kind"], - modifiers: readonly ModifierLike[] | undefined, - name: string | T["name"] | undefined, - type: TypeNode | undefined, - initializer: Expression | undefined - ) { - const node = createBaseBindingLikeDeclaration( - kind, - modifiers, - name, - initializer - ); - node.type = type; - node.transformFlags |= propagateChildFlags(type); - if (type) node.transformFlags |= TransformFlags.ContainsTypeScript; - return node; - } - // // Literals // - function createBaseLiteral( - kind: T["kind"], - text: string - ) { - const node = createBaseToken(kind); - node.text = text; - return node; - } - // @api function createNumericLiteral(value: string | number, numericLiteralFlags: TokenFlags = TokenFlags.None): NumericLiteral { - const node = createBaseLiteral(SyntaxKind.NumericLiteral, typeof value === "number" ? value + "" : value); + const node = createBaseDeclaration(SyntaxKind.NumericLiteral); + node.text = typeof value === "number" ? value + "" : value; node.numericLiteralFlags = numericLiteralFlags; if (numericLiteralFlags & TokenFlags.BinaryOrOctalSpecifier) node.transformFlags |= TransformFlags.ContainsES2015; return node; @@ -1283,13 +1095,15 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode // @api function createBigIntLiteral(value: string | PseudoBigInt): BigIntLiteral { - const node = createBaseLiteral(SyntaxKind.BigIntLiteral, typeof value === "string" ? value : pseudoBigIntToString(value) + "n"); + const node = createBaseToken(SyntaxKind.BigIntLiteral); + node.text = typeof value === "string" ? value : pseudoBigIntToString(value) + "n"; node.transformFlags |= TransformFlags.ContainsESNext; return node; } function createBaseStringLiteral(text: string, isSingleQuote?: boolean) { - const node = createBaseLiteral(SyntaxKind.StringLiteral, text); + const node = createBaseDeclaration(SyntaxKind.StringLiteral); + node.text = text; node.singleQuote = isSingleQuote; return node; } @@ -1311,7 +1125,8 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode // @api function createRegularExpressionLiteral(text: string): RegularExpressionLiteral { - const node = createBaseLiteral(SyntaxKind.RegularExpressionLiteral, text); + const node = createBaseToken(SyntaxKind.RegularExpressionLiteral); + node.text = text; return node; } @@ -1332,21 +1147,16 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode // Identifiers // - function createBaseIdentifier(text: string, originalKeywordKind: SyntaxKind | undefined) { - if (originalKeywordKind === undefined && text) { - originalKeywordKind = stringToToken(text); - } - if (originalKeywordKind === SyntaxKind.Identifier) { - originalKeywordKind = undefined; - } + function createBaseIdentifier(escapedText: __String, originalKeywordKind: SyntaxKind | undefined) { const node = baseFactory.createBaseIdentifierNode(SyntaxKind.Identifier) as Mutable; node.originalKeywordKind = originalKeywordKind; - node.escapedText = escapeLeadingUnderscores(text); + node.escapedText = escapedText; + node.autoGenerateFlags = GeneratedIdentifierFlags.None; return node; } function createBaseGeneratedIdentifier(text: string, autoGenerateFlags: GeneratedIdentifierFlags, prefix: string | GeneratedNamePart | undefined, suffix: string | undefined) { - const node = createBaseIdentifier(text, /*originalKeywordKind*/ undefined) as Mutable; + const node = createBaseIdentifier(escapeLeadingUnderscores(text), /*originalKeywordKind*/ undefined) as Mutable; node.autoGenerateFlags = autoGenerateFlags; node.autoGenerateId = nextAutoGenerateId; node.autoGeneratePrefix = prefix; @@ -1357,18 +1167,29 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode // @api function createIdentifier(text: string, typeArguments?: readonly (TypeNode | TypeParameterDeclaration)[], originalKeywordKind?: SyntaxKind, hasExtendedUnicodeEscape?: boolean): Identifier { - const node = createBaseIdentifier(text, originalKeywordKind); - if (typeArguments) { - // NOTE: we do not use `setChildren` here because typeArguments in an identifier do not contribute to transformations - node.typeArguments = createNodeArray(typeArguments); + if (originalKeywordKind === undefined && text) { + originalKeywordKind = stringToToken(text); } + if (originalKeywordKind === SyntaxKind.Identifier) { + originalKeywordKind = undefined; + } + + const node = createBaseIdentifier(escapeLeadingUnderscores(text), originalKeywordKind); + node.typeArguments = asNodeArray(typeArguments); + node.hasExtendedUnicodeEscape = hasExtendedUnicodeEscape; + node.jsDoc = undefined; // initialized by parser (JsDocContainer) + node.jsDocCache = undefined; // initialized by parser (JsDocContainer) + node.flowNode = undefined; // initialized by binder (FlowContainer) + node.symbol = undefined!; // initialized by checker + + // NOTE: we do not include transform flags of typeArguments in an identifier as they do not contribute to transformations if (node.originalKeywordKind === SyntaxKind.AwaitKeyword) { node.transformFlags |= TransformFlags.ContainsPossibleTopLevelAwait; } - if (hasExtendedUnicodeEscape) { - node.hasExtendedUnicodeEscape = hasExtendedUnicodeEscape; + if (node.hasExtendedUnicodeEscape) { node.transformFlags |= TransformFlags.ContainsES2015; } + return node; } @@ -1419,9 +1240,10 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode return name; } - function createBasePrivateIdentifier(text: string) { + function createBasePrivateIdentifier(escapedText: __String) { const node = baseFactory.createBasePrivateIdentifierNode(SyntaxKind.PrivateIdentifier) as Mutable; - node.escapedText = escapeLeadingUnderscores(text); + node.escapedText = escapedText; + node.autoGenerateFlags = GeneratedIdentifierFlags.None; node.transformFlags |= TransformFlags.ContainsClassFields; return node; } @@ -1429,11 +1251,11 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode // @api function createPrivateIdentifier(text: string): PrivateIdentifier { if (!startsWith(text, "#")) Debug.fail("First character of private identifier must be #: " + text); - return createBasePrivateIdentifier(text); + return createBasePrivateIdentifier(escapeLeadingUnderscores(text)); } function createBaseGeneratedPrivateIdentifier(text: string, autoGenerateFlags: GeneratedIdentifierFlags, prefix: string | GeneratedNamePart | undefined, suffix: string | undefined) { - const node = createBasePrivateIdentifier(text); + const node = createBasePrivateIdentifier(escapeLeadingUnderscores(text)); node.autoGenerateFlags = autoGenerateFlags; node.autoGenerateId = nextAutoGenerateId; node.autoGeneratePrefix = prefix; @@ -1475,11 +1297,12 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode function createToken(token: SyntaxKind.NullKeyword): NullLiteral; function createToken(token: SyntaxKind.TrueKeyword): TrueLiteral; function createToken(token: SyntaxKind.FalseKeyword): FalseLiteral; + function createToken(token: SyntaxKind.EndOfFileToken): EndOfFileToken; + function createToken(token: SyntaxKind.Unknown): Token; function createToken(token: TKind): PunctuationToken; function createToken(token: TKind): KeywordTypeNode; function createToken(token: TKind): ModifierToken; function createToken(token: TKind): KeywordToken; - function createToken(token: TKind): Token; function createToken(token: TKind): Token; function createToken(token: TKind) { Debug.assert(token >= SyntaxKind.FirstToken && token <= SyntaxKind.LastToken, "Invalid token"); @@ -1521,6 +1344,7 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode break; case SyntaxKind.SuperKeyword: transformFlags = TransformFlags.ContainsES2015 | TransformFlags.ContainsLexicalSuper; + (node as Mutable> as Mutable).flowNode = undefined; // initialized by binder (FlowContainer) break; case SyntaxKind.StaticKeyword: transformFlags = TransformFlags.ContainsES2015; @@ -1531,6 +1355,7 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode case SyntaxKind.ThisKeyword: // 'this' indicates a lexical 'this' transformFlags = TransformFlags.ContainsLexicalThis; + (node as Mutable> as Mutable).flowNode = undefined; // initialized by binder (FlowContainer) break; } if (transformFlags) { @@ -1610,6 +1435,8 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode node.transformFlags |= propagateChildFlags(node.left) | propagateIdentifierNameFlags(node.right); + + node.flowNode = undefined; // initialized by binder (FlowContainer) return node; } @@ -1645,14 +1472,16 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode // @api function createTypeParameterDeclaration(modifiers: readonly Modifier[] | undefined, name: string | Identifier, constraint?: TypeNode, defaultType?: TypeNode): TypeParameterDeclaration { - const node = createBaseNamedDeclaration( - SyntaxKind.TypeParameter, - modifiers, - name - ); + const node = createBaseDeclaration(SyntaxKind.TypeParameter); + node.modifiers = asNodeArray(modifiers); + node.name = asName(name); node.constraint = constraint; node.default = defaultType; node.transformFlags = TransformFlags.ContainsTypeScript; + + node.expression = undefined; // initialized by parser to report grammar errors + node.jsDoc = undefined; // initialized by parser (JsDocContainer) + node.jsDocCache = undefined; // initialized by parser (JsDocContainer) return node; } @@ -1675,26 +1504,31 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode type?: TypeNode, initializer?: Expression ) { - const node = createBaseVariableLikeDeclaration( - SyntaxKind.Parameter, - modifiers, - name, - type, - initializer && parenthesizerRules().parenthesizeExpressionForDisallowedComma(initializer) - ); + const node = createBaseDeclaration(SyntaxKind.Parameter); + node.modifiers = asNodeArray(modifiers); node.dotDotDotToken = dotDotDotToken; + node.name = asName(name); node.questionToken = questionToken; + node.type = type; + node.initializer = asInitializer(initializer); + if (isThisIdentifier(node.name)) { node.transformFlags = TransformFlags.ContainsTypeScript; } else { - node.transformFlags |= + node.transformFlags = + propagateChildrenFlags(node.modifiers) | propagateChildFlags(node.dotDotDotToken) | - propagateChildFlags(node.questionToken); - if (questionToken) node.transformFlags |= TransformFlags.ContainsTypeScript; - if (modifiersToFlags(node.modifiers) & ModifierFlags.ParameterPropertyModifier) node.transformFlags |= TransformFlags.ContainsTypeScriptClassSyntax; - if (initializer || dotDotDotToken) node.transformFlags |= TransformFlags.ContainsES2015; + propagateNameFlags(node.name) | + propagateChildFlags(node.questionToken) | + propagateChildFlags(node.initializer) | + (node.questionToken ?? node.type ? TransformFlags.ContainsTypeScript : TransformFlags.None) | + (node.dotDotDotToken ?? node.initializer ? TransformFlags.ContainsES2015 : TransformFlags.None) | + (modifiersToFlags(node.modifiers) & ModifierFlags.ParameterPropertyModifier ? TransformFlags.ContainsTypeScriptClassSyntax : TransformFlags.None); } + + node.jsDoc = undefined; // initialized by parser (JsDocContainer) + node.jsDocCache = undefined; // initialized by parser (JsDocContainer) return node; } @@ -1743,29 +1577,28 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode // @api function createPropertySignature( - modifiers: readonly ModifierLike[] | undefined, + modifiers: readonly Modifier[] | undefined, name: PropertyName | string, questionToken: QuestionToken | undefined, type: TypeNode | undefined ): PropertySignature { - const node = createBaseNamedDeclaration( - SyntaxKind.PropertySignature, - modifiers, - name - ); + const node = createBaseDeclaration(SyntaxKind.PropertySignature); + node.modifiers = asNodeArray(modifiers); + node.name = asName(name); node.type = type; node.questionToken = questionToken; node.transformFlags = TransformFlags.ContainsTypeScript; - // The following properties are used only to report grammar errors - node.initializer = undefined; + node.initializer = undefined; // initialized by parser to report grammar errors + node.jsDoc = undefined; // initialized by parser (JsDocContainer) + node.jsDocCache = undefined; // initialized by parser (JsDocContainer) return node; } // @api function updatePropertySignature( node: PropertySignature, - modifiers: readonly ModifierLike[] | undefined, + modifiers: readonly Modifier[] | undefined, name: PropertyName, questionToken: QuestionToken | undefined, type: TypeNode | undefined @@ -1794,25 +1627,26 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode type: TypeNode | undefined, initializer: Expression | undefined ) { - const node = createBaseVariableLikeDeclaration( - SyntaxKind.PropertyDeclaration, - modifiers, - name, - type, - initializer - ); + const node = createBaseDeclaration(SyntaxKind.PropertyDeclaration); + node.modifiers = asNodeArray(modifiers); + node.name = asName(name); node.questionToken = questionOrExclamationToken && isQuestionToken(questionOrExclamationToken) ? questionOrExclamationToken : undefined; node.exclamationToken = questionOrExclamationToken && isExclamationToken(questionOrExclamationToken) ? questionOrExclamationToken : undefined; - node.transformFlags |= - propagateChildFlags(node.questionToken) | - propagateChildFlags(node.exclamationToken) | + node.type = type; + node.initializer = asInitializer(initializer); + + const isAmbient = node.flags & NodeFlags.Ambient || modifiersToFlags(node.modifiers) & ModifierFlags.Ambient; + + node.transformFlags = + propagateChildrenFlags(node.modifiers) | + propagateNameFlags(node.name) | + propagateChildFlags(node.initializer) | + (isAmbient || node.questionToken || node.exclamationToken || node.type ? TransformFlags.ContainsTypeScript : TransformFlags.None) | + (isComputedPropertyName(node.name) || modifiersToFlags(node.modifiers) & ModifierFlags.Static && node.initializer ? TransformFlags.ContainsTypeScriptClassSyntax : TransformFlags.None) | TransformFlags.ContainsClassFields; - if (isComputedPropertyName(node.name) || (hasStaticModifier(node) && node.initializer)) { - node.transformFlags |= TransformFlags.ContainsTypeScriptClassSyntax; - } - if (questionOrExclamationToken || modifiersToFlags(node.modifiers) & ModifierFlags.Ambient) { - node.transformFlags |= TransformFlags.ContainsTypeScript; - } + + node.jsDoc = undefined; // initialized by parser (JsDocContainer) + node.jsDocCache = undefined; // initialized by parser (JsDocContainer) return node; } @@ -1837,30 +1671,34 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode // @api function createMethodSignature( - modifiers: readonly ModifierLike[] | undefined, + modifiers: readonly Modifier[] | undefined, name: string | PropertyName, questionToken: QuestionToken | undefined, typeParameters: readonly TypeParameterDeclaration[] | undefined, parameters: readonly ParameterDeclaration[], type: TypeNode | undefined ) { - const node = createBaseSignatureDeclaration( - SyntaxKind.MethodSignature, - modifiers, - name, - typeParameters, - parameters, - type - ); + const node = createBaseDeclaration(SyntaxKind.MethodSignature); + node.modifiers = asNodeArray(modifiers); + node.name = asName(name); node.questionToken = questionToken; + node.typeParameters = asNodeArray(typeParameters); + node.parameters = asNodeArray(parameters); + node.type = type; node.transformFlags = TransformFlags.ContainsTypeScript; + + node.jsDoc = undefined; // initialized by parser (JsDocContainer) + node.jsDocCache = undefined; // initialized by parser (JsDocContainer) + node.locals = undefined; // initialized by binder (LocalsContainer) + node.nextContainer = undefined; // initialized by binder (LocalsContainer) + node.typeArguments = undefined; // used in quick info return node; } // @api function updateMethodSignature( node: MethodSignature, - modifiers: readonly ModifierLike[] | undefined, + modifiers: readonly Modifier[] | undefined, name: PropertyName, questionToken: QuestionToken | undefined, typeParameters: NodeArray | undefined, @@ -1888,38 +1726,50 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode type: TypeNode | undefined, body: Block | undefined ) { - const node = createBaseFunctionLikeDeclaration( - SyntaxKind.MethodDeclaration, - modifiers, - name, - typeParameters, - parameters, - type, - body - ); + const node = createBaseDeclaration(SyntaxKind.MethodDeclaration); + node.modifiers = asNodeArray(modifiers); node.asteriskToken = asteriskToken; + node.name = asName(name); node.questionToken = questionToken; - node.transformFlags |= - propagateChildFlags(node.asteriskToken) | - propagateChildFlags(node.questionToken) | - TransformFlags.ContainsES2015; - if (questionToken) { - node.transformFlags |= TransformFlags.ContainsTypeScript; - } - if (modifiersToFlags(node.modifiers) & ModifierFlags.Async) { - if (asteriskToken) { - node.transformFlags |= TransformFlags.ContainsES2018; - } - else { - node.transformFlags |= TransformFlags.ContainsES2017; - } + node.exclamationToken = undefined; // initialized by parser for grammar errors + node.typeParameters = asNodeArray(typeParameters); + node.parameters = createNodeArray(parameters); + node.type = type; + node.body = body; + + if (!node.body) { + node.transformFlags = TransformFlags.ContainsTypeScript; } - else if (asteriskToken) { - node.transformFlags |= TransformFlags.ContainsGenerator; + else { + const isAsync = modifiersToFlags(node.modifiers) & ModifierFlags.Async; + const isGenerator = !!node.asteriskToken; + const isAsyncGenerator = isAsync && isGenerator; + + node.transformFlags = + propagateChildrenFlags(node.modifiers) | + propagateChildFlags(node.asteriskToken) | + propagateNameFlags(node.name) | + propagateChildFlags(node.questionToken) | + propagateChildrenFlags(node.typeParameters) | + propagateChildrenFlags(node.parameters) | + propagateChildFlags(node.type) | + (propagateChildFlags(node.body) & ~TransformFlags.ContainsPossibleTopLevelAwait) | + (isAsyncGenerator ? TransformFlags.ContainsES2018 : + isAsync ? TransformFlags.ContainsES2017 : + isGenerator ? TransformFlags.ContainsGenerator : + TransformFlags.None) | + (node.questionToken || node.typeParameters || node.type ? TransformFlags.ContainsTypeScript : TransformFlags.None) | + TransformFlags.ContainsES2015; } - // The following properties are used only to report grammar errors - node.exclamationToken = undefined; + node.typeArguments = undefined; // used in quick info + node.jsDoc = undefined; // initialized by parser (JsDocContainer) + node.jsDocCache = undefined; // initialized by parser (JsDocContainer) + node.locals = undefined; // initialized by binder (LocalsContainer) + node.nextContainer = undefined; // initialized by binder (LocalsContainer) + node.flowNode = undefined; // initialized by binder (FlowContainer) + node.endFlowNode = undefined; + node.returnFlowNode = undefined; return node; } @@ -1958,18 +1808,18 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode function createClassStaticBlockDeclaration( body: Block ): ClassStaticBlockDeclaration { - const node = createBaseGenericNamedDeclaration( - SyntaxKind.ClassStaticBlockDeclaration, - /*modifiers*/ undefined, - /*name*/ undefined, - /*typeParameters*/ undefined - ); + const node = createBaseDeclaration(SyntaxKind.ClassStaticBlockDeclaration); node.body = body; node.transformFlags = propagateChildFlags(body) | TransformFlags.ContainsClassFields; - // The following properties are used only to report grammar errors - node.illegalDecorators = undefined; - node.modifiers = undefined; + node.illegalDecorators = undefined; // initialized by parser for grammar errors + node.modifiers = undefined; // initialized by parser for grammar errors + node.jsDoc = undefined; // initialized by parser (JsDocContainer) + node.jsDocCache = undefined; // initialized by parser (JsDocContainer) + node.locals = undefined; // initialized by binder (LocalsContainer) + node.nextContainer = undefined; // initialized by binder (LocalsContainer) + node.endFlowNode = undefined; + node.returnFlowNode = undefined; return node; } @@ -1997,21 +1847,27 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode parameters: readonly ParameterDeclaration[], body: Block | undefined ) { - const node = createBaseFunctionLikeDeclaration( - SyntaxKind.Constructor, - modifiers, - /*name*/ undefined, - /*typeParameters*/ undefined, - parameters, - /*type*/ undefined, - body - ); - node.transformFlags |= TransformFlags.ContainsES2015; + const node = createBaseDeclaration(SyntaxKind.Constructor); + node.modifiers = asNodeArray(modifiers); + node.parameters = createNodeArray(parameters); + node.body = body; - // The following properties are used only to report grammar errors - node.illegalDecorators = undefined; - node.typeParameters = undefined; - node.type = undefined; + node.transformFlags = + propagateChildrenFlags(node.modifiers) | + propagateChildrenFlags(node.parameters) | + (propagateChildFlags(node.body) & ~TransformFlags.ContainsPossibleTopLevelAwait) | + TransformFlags.ContainsES2015; + + node.illegalDecorators = undefined; // initialized by parser for grammar errors + node.typeParameters = undefined; // initialized by parser for grammar errors + node.type = undefined; // initialized by parser for grammar errors + node.typeArguments = undefined; // used in quick info + node.jsDoc = undefined; // initialized by parser (JsDocContainer) + node.jsDocCache = undefined; // initialized by parser (JsDocContainer) + node.locals = undefined; // initialized by binder (LocalsContainer) + node.nextContainer = undefined; // initialized by binder (LocalsContainer) + node.endFlowNode = undefined; + node.returnFlowNode = undefined; return node; } @@ -2046,18 +1902,35 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode type: TypeNode | undefined, body: Block | undefined ) { - const node = createBaseFunctionLikeDeclaration( - SyntaxKind.GetAccessor, - modifiers, - name, - /*typeParameters*/ undefined, - parameters, - type, - body - ); + const node = createBaseDeclaration(SyntaxKind.GetAccessor); + node.modifiers = asNodeArray(modifiers); + node.name = asName(name); + node.parameters = createNodeArray(parameters); + node.type = type; + node.body = body; - // The following properties are used only to report grammar errors - node.typeParameters = undefined; + if (!node.body) { + node.transformFlags = TransformFlags.ContainsTypeScript; + } + else { + node.transformFlags = + propagateChildrenFlags(node.modifiers) | + propagateNameFlags(node.name) | + propagateChildrenFlags(node.parameters) | + propagateChildFlags(node.type) | + (propagateChildFlags(node.body) & ~TransformFlags.ContainsPossibleTopLevelAwait) | + (node.type ? TransformFlags.ContainsTypeScript : TransformFlags.None); + } + + node.typeArguments = undefined; // used in quick info + node.typeParameters = undefined; // initialized by parser for grammar errors + node.jsDoc = undefined; // initialized by parser (JsDocContainer) + node.jsDocCache = undefined; // initialized by parser (JsDocContainer) + node.locals = undefined; // initialized by binder (LocalsContainer) + node.nextContainer = undefined; // initialized by binder (LocalsContainer) + node.flowNode = undefined; // initialized by binder (FlowContainer) + node.endFlowNode = undefined; + node.returnFlowNode = undefined; return node; } @@ -2093,19 +1966,34 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode parameters: readonly ParameterDeclaration[], body: Block | undefined ) { - const node = createBaseFunctionLikeDeclaration( - SyntaxKind.SetAccessor, - modifiers, - name, - /*typeParameters*/ undefined, - parameters, - /*type*/ undefined, - body - ); + const node = createBaseDeclaration(SyntaxKind.SetAccessor); + node.modifiers = asNodeArray(modifiers); + node.name = asName(name); + node.parameters = createNodeArray(parameters); + node.body = body; + + if (!node.body) { + node.transformFlags = TransformFlags.ContainsTypeScript; + } + else { + node.transformFlags = + propagateChildrenFlags(node.modifiers) | + propagateNameFlags(node.name) | + propagateChildrenFlags(node.parameters) | + (propagateChildFlags(node.body) & ~TransformFlags.ContainsPossibleTopLevelAwait) | + (node.type ? TransformFlags.ContainsTypeScript : TransformFlags.None); + } - // The following properties are used only to report grammar errors - node.typeParameters = undefined; - node.type = undefined; + node.typeArguments = undefined; // used in quick info + node.typeParameters = undefined; // initialized by parser for grammar errors + node.type = undefined; // initialized by parser for grammar errors + node.jsDoc = undefined; // initialized by parser (JsDocContainer) + node.jsDocCache = undefined; // initialized by parser (JsDocContainer) + node.locals = undefined; // initialized by binder (LocalsContainer) + node.nextContainer = undefined; // initialized by binder (LocalsContainer) + node.flowNode = undefined; // initialized by binder (FlowContainer) + node.endFlowNode = undefined; + node.returnFlowNode = undefined; return node; } @@ -2139,15 +2027,17 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode parameters: readonly ParameterDeclaration[], type: TypeNode | undefined ): CallSignatureDeclaration { - const node = createBaseSignatureDeclaration( - SyntaxKind.CallSignature, - /*modifiers*/ undefined, - /*name*/ undefined, - typeParameters, - parameters, - type - ); + const node = createBaseDeclaration(SyntaxKind.CallSignature); + node.typeParameters = asNodeArray(typeParameters); + node.parameters = asNodeArray(parameters); + node.type = type; node.transformFlags = TransformFlags.ContainsTypeScript; + + node.jsDoc = undefined; // initialized by parser (JsDocContainer) + node.jsDocCache = undefined; // initialized by parser (JsDocContainer) + node.locals = undefined; // initialized by binder (LocalsContainer) + node.nextContainer = undefined; // initialized by binder (LocalsContainer) + node.typeArguments = undefined; // used in quick info return node; } @@ -2171,15 +2061,17 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode parameters: readonly ParameterDeclaration[], type: TypeNode | undefined ): ConstructSignatureDeclaration { - const node = createBaseSignatureDeclaration( - SyntaxKind.ConstructSignature, - /*modifiers*/ undefined, - /*name*/ undefined, - typeParameters, - parameters, - type - ); + const node = createBaseDeclaration(SyntaxKind.ConstructSignature); + node.typeParameters = asNodeArray(typeParameters); + node.parameters = asNodeArray(parameters); + node.type = type; node.transformFlags = TransformFlags.ContainsTypeScript; + + node.jsDoc = undefined; // initialized by parser (JsDocContainer) + node.jsDocCache = undefined; // initialized by parser (JsDocContainer) + node.locals = undefined; // initialized by binder (LocalsContainer) + node.nextContainer = undefined; // initialized by binder (LocalsContainer) + node.typeArguments = undefined; // used in quick info return node; } @@ -2203,15 +2095,18 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode parameters: readonly ParameterDeclaration[], type: TypeNode | undefined ): IndexSignatureDeclaration { - const node = createBaseSignatureDeclaration( - SyntaxKind.IndexSignature, - modifiers, - /*name*/ undefined, - /*typeParameters*/ undefined, - parameters, - type - ); + const node = createBaseDeclaration(SyntaxKind.IndexSignature); + node.modifiers = asNodeArray(modifiers); + node.parameters = asNodeArray(parameters); + node.type = type!; // TODO(rbuckton): We mark this as required in IndexSignatureDeclaration, but it looks like the parser allows it to be elided. node.transformFlags = TransformFlags.ContainsTypeScript; + + node.illegalDecorators = undefined; // initialized by parser to report grammar errors + node.jsDoc = undefined; // initialized by parser (JsDocContainer) + node.jsDocCache = undefined; // initialized by parser (JsDocContainer) + node.locals = undefined; // initialized by binder (LocalsContainer) + node.nextContainer = undefined; // initialized by binder (LocalsContainer) + node.typeArguments = undefined; // used in quick info return node; } @@ -2295,20 +2190,20 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode function createFunctionTypeNode( typeParameters: readonly TypeParameterDeclaration[] | undefined, parameters: readonly ParameterDeclaration[], - type: TypeNode | undefined + type: TypeNode ): FunctionTypeNode { - const node = createBaseSignatureDeclaration( - SyntaxKind.FunctionType, - /*modifiers*/ undefined, - /*name*/ undefined, - typeParameters, - parameters, - type - ); + const node = createBaseDeclaration(SyntaxKind.FunctionType); + node.typeParameters = asNodeArray(typeParameters); + node.parameters = asNodeArray(parameters); + node.type = type; node.transformFlags = TransformFlags.ContainsTypeScript; - // The following properties are used only to report grammar errors - node.modifiers = undefined; + node.modifiers = undefined; // initialized by parser for grammar errors + node.jsDoc = undefined; // initialized by parser (JsDocContainer) + node.jsDocCache = undefined; // initialized by parser (JsDocContainer) + node.locals = undefined; // initialized by binder (LocalsContainer) + node.nextContainer = undefined; // initialized by binder (LocalsContainer) + node.typeArguments = undefined; // used in quick info return node; } @@ -2317,7 +2212,7 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode node: FunctionTypeNode, typeParameters: NodeArray | undefined, parameters: NodeArray, - type: TypeNode | undefined + type: TypeNode ) { return node.typeParameters !== typeParameters || node.parameters !== parameters @@ -2344,17 +2239,20 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode modifiers: readonly Modifier[] | undefined, typeParameters: readonly TypeParameterDeclaration[] | undefined, parameters: readonly ParameterDeclaration[], - type: TypeNode | undefined + type: TypeNode ): ConstructorTypeNode { - const node = createBaseSignatureDeclaration( - SyntaxKind.ConstructorType, - modifiers, - /*name*/ undefined, - typeParameters, - parameters, - type - ); + const node = createBaseDeclaration(SyntaxKind.ConstructorType); + node.modifiers = asNodeArray(modifiers); + node.typeParameters = asNodeArray(typeParameters); + node.parameters = asNodeArray(parameters); + node.type = type; node.transformFlags = TransformFlags.ContainsTypeScript; + + node.jsDoc = undefined; // initialized by parser (JsDocContainer) + node.jsDocCache = undefined; // initialized by parser (JsDocContainer) + node.locals = undefined; // initialized by binder (LocalsContainer) + node.nextContainer = undefined; // initialized by binder (LocalsContainer) + node.typeArguments = undefined; // used in quick info return node; } @@ -2362,7 +2260,7 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode function createConstructorTypeNode2( typeParameters: readonly TypeParameterDeclaration[] | undefined, parameters: readonly ParameterDeclaration[], - type: TypeNode | undefined + type: TypeNode ): ConstructorTypeNode { return createConstructorTypeNode1(/*modifiers*/ undefined, typeParameters, parameters, type); } @@ -2379,7 +2277,7 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode modifiers: readonly Modifier[] | undefined, typeParameters: NodeArray | undefined, parameters: NodeArray, - type: TypeNode | undefined + type: TypeNode ) { return node.modifiers !== modifiers || node.typeParameters !== typeParameters @@ -2394,7 +2292,7 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode node: ConstructorTypeNode, typeParameters: NodeArray | undefined, parameters: NodeArray, - type: TypeNode | undefined + type: TypeNode ) { return updateConstructorTypeNode1(node, node.modifiers, typeParameters, parameters, type); } @@ -2418,7 +2316,7 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode // @api function createTypeLiteralNode(members: readonly TypeElement[] | undefined) { - const node = createBaseNode(SyntaxKind.TypeLiteral); + const node = createBaseDeclaration(SyntaxKind.TypeLiteral); node.members = createNodeArray(members); node.transformFlags = TransformFlags.ContainsTypeScript; return node; @@ -2463,12 +2361,15 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode // @api function createNamedTupleMember(dotDotDotToken: DotDotDotToken | undefined, name: Identifier, questionToken: QuestionToken | undefined, type: TypeNode) { - const node = createBaseNode(SyntaxKind.NamedTupleMember); + const node = createBaseDeclaration(SyntaxKind.NamedTupleMember); node.dotDotDotToken = dotDotDotToken; node.name = name; node.questionToken = questionToken; node.type = type; node.transformFlags = TransformFlags.ContainsTypeScript; + + node.jsDoc = undefined; // initialized by parser (JsDocContainer) + node.jsDocCache = undefined; // initialized by parser (JsDocContainer) return node; } @@ -2553,6 +2454,9 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode node.trueType = trueType; node.falseType = falseType; node.transformFlags = TransformFlags.ContainsTypeScript; + + node.locals = undefined; // initialized by binder (LocalsContainer) + node.nextContainer = undefined; // initialized by binder (LocalsContainer) return node; } @@ -2693,7 +2597,7 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode // @api function createMappedTypeNode(readonlyToken: ReadonlyKeyword | PlusToken | MinusToken | undefined, typeParameter: TypeParameterDeclaration, nameType: TypeNode | undefined, questionToken: QuestionToken | PlusToken | MinusToken | undefined, type: TypeNode | undefined, members: readonly TypeElement[] | undefined): MappedTypeNode { - const node = createBaseNode(SyntaxKind.MappedType); + const node = createBaseDeclaration(SyntaxKind.MappedType); node.readonlyToken = readonlyToken; node.typeParameter = typeParameter; node.nameType = nameType; @@ -2701,6 +2605,9 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode node.type = type; node.members = members && createNodeArray(members); node.transformFlags = TransformFlags.ContainsTypeScript; + + node.locals = undefined; // initialized by binder (LocalsContainer) + node.nextContainer = undefined; // initialized by binder (LocalsContainer) return node; } @@ -2778,23 +2685,20 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode // @api function createBindingElement(dotDotDotToken: DotDotDotToken | undefined, propertyName: string | PropertyName | undefined, name: string | BindingName, initializer?: Expression) { - const node = createBaseBindingLikeDeclaration( - SyntaxKind.BindingElement, - /*modifiers*/ undefined, - name, - initializer && parenthesizerRules().parenthesizeExpressionForDisallowedComma(initializer) - ); - node.propertyName = asName(propertyName); + const node = createBaseDeclaration(SyntaxKind.BindingElement); node.dotDotDotToken = dotDotDotToken; + node.propertyName = asName(propertyName); + node.name = asName(name); + node.initializer = asInitializer(initializer); node.transformFlags |= propagateChildFlags(node.dotDotDotToken) | + propagateNameFlags(node.propertyName) | + propagateNameFlags(node.name) | + propagateChildFlags(node.initializer) | + (node.dotDotDotToken ? TransformFlags.ContainsRestOrSpread : TransformFlags.None) | TransformFlags.ContainsES2015; - if (node.propertyName) { - node.transformFlags |= isIdentifier(node.propertyName) ? - propagateIdentifierNameFlags(node.propertyName) : - propagateChildFlags(node.propertyName); - } - if (dotDotDotToken) node.transformFlags |= TransformFlags.ContainsRestOrSpread; + + node.flowNode = undefined; // initialized by binder (FlowContainer) return node; } @@ -2812,15 +2716,9 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode // Expression // - function createBaseExpression(kind: T["kind"]) { - const node = createBaseNode(kind); - // the following properties are commonly set by the checker/binder - return node; - } - // @api function createArrayLiteralExpression(elements?: readonly Expression[], multiLine?: boolean) { - const node = createBaseExpression(SyntaxKind.ArrayLiteralExpression); + const node = createBaseNode(SyntaxKind.ArrayLiteralExpression); // Ensure we add a trailing comma for something like `[NumericLiteral(1), NumericLiteral(2), OmittedExpresion]` so that // we end up with `[1, 2, ,]` instead of `[1, 2, ]` otherwise the `OmittedExpression` will just end up being treated like // a trailing comma. @@ -2841,10 +2739,13 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode // @api function createObjectLiteralExpression(properties?: readonly ObjectLiteralElementLike[], multiLine?: boolean) { - const node = createBaseExpression(SyntaxKind.ObjectLiteralExpression); + const node = createBaseDeclaration(SyntaxKind.ObjectLiteralExpression); node.properties = createNodeArray(properties); node.multiLine = multiLine; node.transformFlags |= propagateChildrenFlags(node.properties); + + node.jsDoc = undefined; // initialized by parser (JsDocContainer) + node.jsDocCache = undefined; // initialized by parser (JsDocContainer) return node; } @@ -2855,16 +2756,31 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode : node; } - // @api - function createPropertyAccessExpression(expression: Expression, name: string | Identifier | PrivateIdentifier) { - const node = createBaseExpression(SyntaxKind.PropertyAccessExpression); - node.expression = parenthesizerRules().parenthesizeLeftSideOfAccess(expression, /*optionalChain*/ false); - node.name = asName(name); + function createBasePropertyAccessExpression(expression: LeftHandSideExpression, questionDotToken: QuestionDotToken | undefined, name: MemberName) { + const node = createBaseDeclaration(SyntaxKind.PropertyAccessExpression); + node.expression = expression; + node.questionDotToken = questionDotToken; + node.name = name; node.transformFlags = propagateChildFlags(node.expression) | + propagateChildFlags(node.questionDotToken) | (isIdentifier(node.name) ? propagateIdentifierNameFlags(node.name) : propagateChildFlags(node.name) | TransformFlags.ContainsPrivateIdentifierInExpression); + + node.jsDoc = undefined; // initialized by parser (JsDocContainer) + node.jsDocCache = undefined; // initialized by parser (JsDocContainer) + node.flowNode = undefined; // initialized by binder (FlowContainer) + return node; + } + + // @api + function createPropertyAccessExpression(expression: Expression, name: string | Identifier | PrivateIdentifier) { + const node = createBasePropertyAccessExpression( + parenthesizerRules().parenthesizeLeftSideOfAccess(expression, /*optionalChain*/ false), + /*questionDotToken*/ undefined, + asName(name) + ); if (isSuperKeyword(expression)) { // super method calls require a lexical 'this' // super method calls require 'super' hoisting in ES2017 and ES2018 async functions and async generators @@ -2888,18 +2804,13 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode // @api function createPropertyAccessChain(expression: Expression, questionDotToken: QuestionDotToken | undefined, name: string | Identifier | PrivateIdentifier) { - const node = createBaseExpression(SyntaxKind.PropertyAccessExpression); + const node = createBasePropertyAccessExpression( + parenthesizerRules().parenthesizeLeftSideOfAccess(expression, /*optionalChain*/ true), + questionDotToken, + asName(name) + ) as Mutable; node.flags |= NodeFlags.OptionalChain; - node.expression = parenthesizerRules().parenthesizeLeftSideOfAccess(expression, /*optionalChain*/ true); - node.questionDotToken = questionDotToken; - node.name = asName(name); - node.transformFlags |= - TransformFlags.ContainsES2020 | - propagateChildFlags(node.expression) | - propagateChildFlags(node.questionDotToken) | - (isIdentifier(node.name) ? - propagateIdentifierNameFlags(node.name) : - propagateChildFlags(node.name) | TransformFlags.ContainsPrivateIdentifierInExpression); + node.transformFlags |= TransformFlags.ContainsES2020; return node; } @@ -2915,14 +2826,29 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode : node; } - // @api - function createElementAccessExpression(expression: Expression, index: number | Expression) { - const node = createBaseExpression(SyntaxKind.ElementAccessExpression); - node.expression = parenthesizerRules().parenthesizeLeftSideOfAccess(expression, /*optionalChain*/ false); - node.argumentExpression = asExpression(index); + function createBaseElementAccessExpression(expression: LeftHandSideExpression, questionDotToken: QuestionDotToken | undefined, argumentExpression: Expression) { + const node = createBaseDeclaration(SyntaxKind.ElementAccessExpression); + node.expression = expression; + node.questionDotToken = questionDotToken; + node.argumentExpression = argumentExpression; node.transformFlags |= propagateChildFlags(node.expression) | + propagateChildFlags(node.questionDotToken) | propagateChildFlags(node.argumentExpression); + + node.jsDoc = undefined; // initialized by parser (JsDocContainer) + node.jsDocCache = undefined; // initialized by parser (JsDocContainer) + node.flowNode = undefined; // initialized by binder (FlowContainer) + return node; + } + + // @api + function createElementAccessExpression(expression: Expression, index: number | Expression) { + const node = createBaseElementAccessExpression( + parenthesizerRules().parenthesizeLeftSideOfAccess(expression, /*optionalChain*/ false), + /*questionDotToken*/ undefined, + asExpression(index) + ); if (isSuperKeyword(expression)) { // super method calls require a lexical 'this' // super method calls require 'super' hoisting in ES2017 and ES2018 async functions and async generators @@ -2946,16 +2872,13 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode // @api function createElementAccessChain(expression: Expression, questionDotToken: QuestionDotToken | undefined, index: number | Expression) { - const node = createBaseExpression(SyntaxKind.ElementAccessExpression); + const node = createBaseElementAccessExpression( + parenthesizerRules().parenthesizeLeftSideOfAccess(expression, /*optionalChain*/ true), + questionDotToken, + asExpression(index) + ) as Mutable; node.flags |= NodeFlags.OptionalChain; - node.expression = parenthesizerRules().parenthesizeLeftSideOfAccess(expression, /*optionalChain*/ true); - node.questionDotToken = questionDotToken; - node.argumentExpression = asExpression(index); - node.transformFlags |= - propagateChildFlags(node.expression) | - propagateChildFlags(node.questionDotToken) | - propagateChildFlags(node.argumentExpression) | - TransformFlags.ContainsES2020; + node.transformFlags |= TransformFlags.ContainsES2020; return node; } @@ -2971,25 +2894,37 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode : node; } - // @api - function createCallExpression(expression: Expression, typeArguments: readonly TypeNode[] | undefined, argumentsArray: readonly Expression[] | undefined) { - const node = createBaseExpression(SyntaxKind.CallExpression); - node.expression = parenthesizerRules().parenthesizeLeftSideOfAccess(expression, /*optionalChain*/ false); - node.typeArguments = asNodeArray(typeArguments); - node.arguments = parenthesizerRules().parenthesizeExpressionsOfCommaDelimitedList(createNodeArray(argumentsArray)); + function createBaseCallExpression(expression: LeftHandSideExpression, questionDotToken: QuestionDotToken | undefined, typeArguments: NodeArray | undefined, argumentsArray: NodeArray) { + const node = createBaseDeclaration(SyntaxKind.CallExpression); + node.expression = expression; + node.questionDotToken = questionDotToken; + node.typeArguments = typeArguments; + node.arguments = argumentsArray; node.transformFlags |= propagateChildFlags(node.expression) | + propagateChildFlags(node.questionDotToken) | propagateChildrenFlags(node.typeArguments) | propagateChildrenFlags(node.arguments); if (node.typeArguments) { node.transformFlags |= TransformFlags.ContainsTypeScript; } + if (isSuperProperty(node.expression)) { + node.transformFlags |= TransformFlags.ContainsLexicalThis; + } + return node; + } + + // @api + function createCallExpression(expression: Expression, typeArguments: readonly TypeNode[] | undefined, argumentsArray: readonly Expression[] | undefined) { + const node = createBaseCallExpression( + parenthesizerRules().parenthesizeLeftSideOfAccess(expression, /*optionalChain*/ false), + /*questionDotToken*/ undefined, + asNodeArray(typeArguments), + parenthesizerRules().parenthesizeExpressionsOfCommaDelimitedList(createNodeArray(argumentsArray)), + ); if (isImportKeyword(node.expression)) { node.transformFlags |= TransformFlags.ContainsDynamicImport; } - else if (isSuperProperty(node.expression)) { - node.transformFlags |= TransformFlags.ContainsLexicalThis; - } return node; } @@ -3007,24 +2942,14 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode // @api function createCallChain(expression: Expression, questionDotToken: QuestionDotToken | undefined, typeArguments: readonly TypeNode[] | undefined, argumentsArray: readonly Expression[] | undefined) { - const node = createBaseExpression(SyntaxKind.CallExpression); + const node = createBaseCallExpression( + parenthesizerRules().parenthesizeLeftSideOfAccess(expression, /*optionalChain*/ true), + questionDotToken, + asNodeArray(typeArguments), + parenthesizerRules().parenthesizeExpressionsOfCommaDelimitedList(createNodeArray(argumentsArray)) + ) as Mutable; node.flags |= NodeFlags.OptionalChain; - node.expression = parenthesizerRules().parenthesizeLeftSideOfAccess(expression, /*optionalChain*/ true); - node.questionDotToken = questionDotToken; - node.typeArguments = asNodeArray(typeArguments); - node.arguments = parenthesizerRules().parenthesizeExpressionsOfCommaDelimitedList(createNodeArray(argumentsArray)); - node.transformFlags |= - propagateChildFlags(node.expression) | - propagateChildFlags(node.questionDotToken) | - propagateChildrenFlags(node.typeArguments) | - propagateChildrenFlags(node.arguments) | - TransformFlags.ContainsES2020; - if (node.typeArguments) { - node.transformFlags |= TransformFlags.ContainsTypeScript; - } - if (isSuperProperty(node.expression)) { - node.transformFlags |= TransformFlags.ContainsLexicalThis; - } + node.transformFlags |= TransformFlags.ContainsES2020; return node; } @@ -3041,7 +2966,7 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode // @api function createNewExpression(expression: Expression, typeArguments: readonly TypeNode[] | undefined, argumentsArray: readonly Expression[] | undefined) { - const node = createBaseExpression(SyntaxKind.NewExpression); + const node = createBaseDeclaration(SyntaxKind.NewExpression); node.expression = parenthesizerRules().parenthesizeExpressionOfNew(expression); node.typeArguments = asNodeArray(typeArguments); node.arguments = argumentsArray ? parenthesizerRules().parenthesizeExpressionsOfCommaDelimitedList(argumentsArray) : undefined; @@ -3067,7 +2992,7 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode // @api function createTaggedTemplateExpression(tag: Expression, typeArguments: readonly TypeNode[] | undefined, template: TemplateLiteral) { - const node = createBaseExpression(SyntaxKind.TaggedTemplateExpression); + const node = createBaseNode(SyntaxKind.TaggedTemplateExpression); node.tag = parenthesizerRules().parenthesizeLeftSideOfAccess(tag, /*optionalChain*/ false); node.typeArguments = asNodeArray(typeArguments); node.template = template; @@ -3096,7 +3021,7 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode // @api function createTypeAssertion(type: TypeNode, expression: Expression) { - const node = createBaseExpression(SyntaxKind.TypeAssertionExpression); + const node = createBaseNode(SyntaxKind.TypeAssertionExpression); node.expression = parenthesizerRules().parenthesizeOperandOfPrefixUnary(expression); node.type = type; node.transformFlags |= @@ -3116,9 +3041,12 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode // @api function createParenthesizedExpression(expression: Expression) { - const node = createBaseExpression(SyntaxKind.ParenthesizedExpression); + const node = createBaseNode(SyntaxKind.ParenthesizedExpression); node.expression = expression; node.transformFlags = propagateChildFlags(node.expression); + + node.jsDoc = undefined; // initialized by parser (JsDocContainer) + node.jsDocCache = undefined; // initialized by parser (JsDocContainer) return node; } @@ -3131,7 +3059,7 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode // @api function createFunctionExpression( - modifiers: readonly ModifierLike[] | undefined, + modifiers: readonly Modifier[] | undefined, asteriskToken: AsteriskToken | undefined, name: string | Identifier | undefined, typeParameters: readonly TypeParameterDeclaration[] | undefined, @@ -3139,38 +3067,49 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode type: TypeNode | undefined, body: Block ) { - const node = createBaseFunctionLikeDeclaration( - SyntaxKind.FunctionExpression, - modifiers, - name, - typeParameters, - parameters, - type, - body - ); + const node = createBaseDeclaration(SyntaxKind.FunctionExpression); + node.modifiers = asNodeArray(modifiers); node.asteriskToken = asteriskToken; - node.transformFlags |= propagateChildFlags(node.asteriskToken); - if (node.typeParameters) { - node.transformFlags |= TransformFlags.ContainsTypeScript; - } - if (modifiersToFlags(node.modifiers) & ModifierFlags.Async) { - if (node.asteriskToken) { - node.transformFlags |= TransformFlags.ContainsES2018; - } - else { - node.transformFlags |= TransformFlags.ContainsES2017; - } - } - else if (node.asteriskToken) { - node.transformFlags |= TransformFlags.ContainsGenerator; - } + node.name = asName(name); + node.typeParameters = asNodeArray(typeParameters); + node.parameters = createNodeArray(parameters); + node.type = type; + node.body = body; + + const isAsync = modifiersToFlags(node.modifiers) & ModifierFlags.Async; + const isGenerator = !!node.asteriskToken; + const isAsyncGenerator = isAsync && isGenerator; + + node.transformFlags = + propagateChildrenFlags(node.modifiers) | + propagateChildFlags(node.asteriskToken) | + propagateNameFlags(node.name) | + propagateChildrenFlags(node.typeParameters) | + propagateChildrenFlags(node.parameters) | + propagateChildFlags(node.type) | + (propagateChildFlags(node.body) & ~TransformFlags.ContainsPossibleTopLevelAwait) | + (isAsyncGenerator ? TransformFlags.ContainsES2018 : + isAsync ? TransformFlags.ContainsES2017 : + isGenerator ? TransformFlags.ContainsGenerator : + TransformFlags.None) | + (node.typeParameters || node.type ? TransformFlags.ContainsTypeScript : TransformFlags.None) | + TransformFlags.ContainsHoistedDeclarationOrCompletion; + + node.typeArguments = undefined; // used in quick info + node.jsDoc = undefined; // initialized by parser (JsDocContainer) + node.jsDocCache = undefined; // initialized by parser (JsDocContainer) + node.locals = undefined; // initialized by binder (LocalsContainer) + node.nextContainer = undefined; // initialized by binder (LocalsContainer) + node.flowNode = undefined; // initialized by binder (FlowContainer) + node.endFlowNode = undefined; + node.returnFlowNode = undefined; return node; } // @api function updateFunctionExpression( node: FunctionExpression, - modifiers: readonly ModifierLike[] | undefined, + modifiers: readonly Modifier[] | undefined, asteriskToken: AsteriskToken | undefined, name: Identifier | undefined, typeParameters: readonly TypeParameterDeclaration[] | undefined, @@ -3191,36 +3130,49 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode // @api function createArrowFunction( - modifiers: readonly ModifierLike[] | undefined, + modifiers: readonly Modifier[] | undefined, typeParameters: readonly TypeParameterDeclaration[] | undefined, parameters: readonly ParameterDeclaration[], type: TypeNode | undefined, equalsGreaterThanToken: EqualsGreaterThanToken | undefined, body: ConciseBody ) { - const node = createBaseFunctionLikeDeclaration( - SyntaxKind.ArrowFunction, - modifiers, - /*name*/ undefined, - typeParameters, - parameters, - type, - parenthesizerRules().parenthesizeConciseBodyOfArrowFunction(body) - ); + const node = createBaseDeclaration(SyntaxKind.ArrowFunction); + node.modifiers = asNodeArray(modifiers); + node.typeParameters = asNodeArray(typeParameters); + node.parameters = createNodeArray(parameters); + node.type = type; node.equalsGreaterThanToken = equalsGreaterThanToken ?? createToken(SyntaxKind.EqualsGreaterThanToken); - node.transformFlags |= + node.body = parenthesizerRules().parenthesizeConciseBodyOfArrowFunction(body); + + const isAsync = modifiersToFlags(node.modifiers) & ModifierFlags.Async; + + node.transformFlags = + propagateChildrenFlags(node.modifiers) | + propagateChildrenFlags(node.typeParameters) | + propagateChildrenFlags(node.parameters) | + propagateChildFlags(node.type) | propagateChildFlags(node.equalsGreaterThanToken) | + (propagateChildFlags(node.body) & ~TransformFlags.ContainsPossibleTopLevelAwait) | + (node.typeParameters || node.type ? TransformFlags.ContainsTypeScript : TransformFlags.None) | + (isAsync ? TransformFlags.ContainsES2017 | TransformFlags.ContainsLexicalThis : TransformFlags.None) | TransformFlags.ContainsES2015; - if (modifiersToFlags(node.modifiers) & ModifierFlags.Async) { - node.transformFlags |= TransformFlags.ContainsES2017 | TransformFlags.ContainsLexicalThis; - } + + node.typeArguments = undefined; // used in quick info + node.jsDoc = undefined; // initialized by parser (JsDocContainer) + node.jsDocCache = undefined; // initialized by parser (JsDocContainer) + node.locals = undefined; // initialized by binder (LocalsContainer) + node.nextContainer = undefined; // initialized by binder (LocalsContainer) + node.flowNode = undefined; // initialized by binder (FlowContainer) + node.endFlowNode = undefined; + node.returnFlowNode = undefined; return node; } // @api function updateArrowFunction( node: ArrowFunction, - modifiers: readonly ModifierLike[] | undefined, + modifiers: readonly Modifier[] | undefined, typeParameters: readonly TypeParameterDeclaration[] | undefined, parameters: readonly ParameterDeclaration[], type: TypeNode | undefined, @@ -3239,7 +3191,7 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode // @api function createDeleteExpression(expression: Expression) { - const node = createBaseExpression(SyntaxKind.DeleteExpression); + const node = createBaseNode(SyntaxKind.DeleteExpression); node.expression = parenthesizerRules().parenthesizeOperandOfPrefixUnary(expression); node.transformFlags |= propagateChildFlags(node.expression); return node; @@ -3254,7 +3206,7 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode // @api function createTypeOfExpression(expression: Expression) { - const node = createBaseExpression(SyntaxKind.TypeOfExpression); + const node = createBaseNode(SyntaxKind.TypeOfExpression); node.expression = parenthesizerRules().parenthesizeOperandOfPrefixUnary(expression); node.transformFlags |= propagateChildFlags(node.expression); return node; @@ -3269,7 +3221,7 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode // @api function createVoidExpression(expression: Expression) { - const node = createBaseExpression(SyntaxKind.VoidExpression); + const node = createBaseNode(SyntaxKind.VoidExpression); node.expression = parenthesizerRules().parenthesizeOperandOfPrefixUnary(expression); node.transformFlags |= propagateChildFlags(node.expression); return node; @@ -3284,7 +3236,7 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode // @api function createAwaitExpression(expression: Expression) { - const node = createBaseExpression(SyntaxKind.AwaitExpression); + const node = createBaseNode(SyntaxKind.AwaitExpression); node.expression = parenthesizerRules().parenthesizeOperandOfPrefixUnary(expression); node.transformFlags |= propagateChildFlags(node.expression) | @@ -3303,7 +3255,7 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode // @api function createPrefixUnaryExpression(operator: PrefixUnaryOperator, operand: Expression) { - const node = createBaseExpression(SyntaxKind.PrefixUnaryExpression); + const node = createBaseNode(SyntaxKind.PrefixUnaryExpression); node.operator = operator; node.operand = parenthesizerRules().parenthesizeOperandOfPrefixUnary(operand); node.transformFlags |= propagateChildFlags(node.operand); @@ -3327,7 +3279,7 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode // @api function createPostfixUnaryExpression(operand: Expression, operator: PostfixUnaryOperator) { - const node = createBaseExpression(SyntaxKind.PostfixUnaryExpression); + const node = createBaseNode(SyntaxKind.PostfixUnaryExpression); node.operator = operator; node.operand = parenthesizerRules().parenthesizeOperandOfPostfixUnary(operand); node.transformFlags |= propagateChildFlags(node.operand); @@ -3350,7 +3302,7 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode // @api function createBinaryExpression(left: Expression, operator: BinaryOperator | BinaryOperatorToken, right: Expression) { - const node = createBaseExpression(SyntaxKind.BinaryExpression); + const node = createBaseDeclaration(SyntaxKind.BinaryExpression); const operatorToken = asToken(operator); const operatorKind = operatorToken.kind; node.left = parenthesizerRules().parenthesizeLeftSideOfBinary(operatorKind, left); @@ -3387,6 +3339,9 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode if (operatorKind === SyntaxKind.InKeyword && isPrivateIdentifier(node.left)) { node.transformFlags |= TransformFlags.ContainsPrivateIdentifierInExpression; } + + node.jsDoc = undefined; // initialized by parser (JsDocContainer) + node.jsDocCache = undefined; // initialized by parser (JsDocContainer) return node; } @@ -3422,7 +3377,7 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode // @api function createConditionalExpression(condition: Expression, questionToken: QuestionToken | undefined, whenTrue: Expression, colonToken: ColonToken | undefined, whenFalse: Expression) { - const node = createBaseExpression(SyntaxKind.ConditionalExpression); + const node = createBaseNode(SyntaxKind.ConditionalExpression); node.condition = parenthesizerRules().parenthesizeConditionOfConditionalExpression(condition); node.questionToken = questionToken ?? createToken(SyntaxKind.QuestionToken); node.whenTrue = parenthesizerRules().parenthesizeBranchOfConditionalExpression(whenTrue); @@ -3457,7 +3412,7 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode // @api function createTemplateExpression(head: TemplateHead, templateSpans: readonly TemplateSpan[]) { - const node = createBaseExpression(SyntaxKind.TemplateExpression); + const node = createBaseNode(SyntaxKind.TemplateExpression); node.head = head; node.templateSpans = createNodeArray(templateSpans); node.transformFlags |= @@ -3475,7 +3430,7 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode : node; } - function createTemplateLiteralLikeNodeChecked(kind: TemplateLiteralToken["kind"], text: string | undefined, rawText: string | undefined, templateFlags = TokenFlags.None) { + function checkTemplateLiteralLikeNode(kind: TemplateLiteralToken["kind"], text: string | undefined, rawText: string | undefined, templateFlags = TokenFlags.None) { Debug.assert(!(templateFlags & ~TokenFlags.TemplateLiteralLikeFlags), "Unsupported template flags."); // NOTE: without the assignment to `undefined`, we don't narrow the initial type of `cooked`. // eslint-disable-next-line no-undef-init @@ -3495,46 +3450,74 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode else if (cooked !== undefined) { Debug.assert(text === cooked, "Expected argument 'text' to be the normalized (i.e. 'cooked') version of argument 'rawText'."); } - return createTemplateLiteralLikeNode(kind, text, rawText, templateFlags); + return text; } - // @api - function createTemplateLiteralLikeNode(kind: TemplateLiteralToken["kind"], text: string, rawText: string | undefined, templateFlags: TokenFlags | undefined) { + function getTransformFlagsOfTemplateLiteralLike(templateFlags: TokenFlags) { + let transformFlags = TransformFlags.ContainsES2015; + if (templateFlags) { + transformFlags |= TransformFlags.ContainsES2018; + } + return transformFlags; + } + + // NOTE: `createTemplateLiteralLikeToken` and `createTemplateLiteralLikeDeclaration` are identical except for + // the underlying nodes they create. To avoid polymorphism due to two different node shapes, these + // functions are intentionally duplicated. + function createTemplateLiteralLikeToken(kind: TemplateLiteralToken["kind"], text: string, rawText: string | undefined, templateFlags: TokenFlags | undefined) { const node = createBaseToken(kind); node.text = text; node.rawText = rawText; node.templateFlags = templateFlags! & TokenFlags.TemplateLiteralLikeFlags; - node.transformFlags |= TransformFlags.ContainsES2015; - if (node.templateFlags) { - node.transformFlags |= TransformFlags.ContainsES2018; - } + node.transformFlags = getTransformFlagsOfTemplateLiteralLike(node.templateFlags); + return node; + } + + function createTemplateLiteralLikeDeclaration(kind: SyntaxKind.NoSubstitutionTemplateLiteral, text: string, rawText: string | undefined, templateFlags: TokenFlags | undefined) { + const node = createBaseDeclaration(kind); + node.text = text; + node.rawText = rawText; + node.templateFlags = templateFlags! & TokenFlags.TemplateLiteralLikeFlags; + node.transformFlags = getTransformFlagsOfTemplateLiteralLike(node.templateFlags); return node; } + // @api + function createTemplateLiteralLikeNode(kind: TemplateLiteralToken["kind"], text: string, rawText: string | undefined, templateFlags: TokenFlags | undefined) { + if (kind === SyntaxKind.NoSubstitutionTemplateLiteral) { + return createTemplateLiteralLikeDeclaration(kind, text, rawText, templateFlags); + } + return createTemplateLiteralLikeToken(kind, text, rawText, templateFlags); + } + // @api function createTemplateHead(text: string | undefined, rawText?: string, templateFlags?: TokenFlags) { - return createTemplateLiteralLikeNodeChecked(SyntaxKind.TemplateHead, text, rawText, templateFlags) as TemplateHead; + text = checkTemplateLiteralLikeNode(SyntaxKind.TemplateHead, text, rawText, templateFlags); + return createTemplateLiteralLikeNode(SyntaxKind.TemplateHead, text, rawText, templateFlags) as TemplateHead; } // @api function createTemplateMiddle(text: string | undefined, rawText?: string, templateFlags?: TokenFlags) { - return createTemplateLiteralLikeNodeChecked(SyntaxKind.TemplateMiddle, text, rawText, templateFlags) as TemplateMiddle; + text = checkTemplateLiteralLikeNode(SyntaxKind.TemplateHead, text, rawText, templateFlags); + return createTemplateLiteralLikeNode(SyntaxKind.TemplateMiddle, text, rawText, templateFlags) as TemplateMiddle; } // @api function createTemplateTail(text: string | undefined, rawText?: string, templateFlags?: TokenFlags) { - return createTemplateLiteralLikeNodeChecked(SyntaxKind.TemplateTail, text, rawText, templateFlags) as TemplateTail; + text = checkTemplateLiteralLikeNode(SyntaxKind.TemplateHead, text, rawText, templateFlags); + return createTemplateLiteralLikeNode(SyntaxKind.TemplateTail, text, rawText, templateFlags) as TemplateTail; } // @api function createNoSubstitutionTemplateLiteral(text: string | undefined, rawText?: string, templateFlags?: TokenFlags) { - return createTemplateLiteralLikeNodeChecked(SyntaxKind.NoSubstitutionTemplateLiteral, text, rawText, templateFlags) as NoSubstitutionTemplateLiteral; + text = checkTemplateLiteralLikeNode(SyntaxKind.TemplateHead, text, rawText, templateFlags); + return createTemplateLiteralLikeDeclaration(SyntaxKind.NoSubstitutionTemplateLiteral, text, rawText, templateFlags) as NoSubstitutionTemplateLiteral; } // @api function createYieldExpression(asteriskToken: AsteriskToken | undefined, expression: Expression | undefined): YieldExpression { Debug.assert(!asteriskToken || !!expression, "A `YieldExpression` with an asteriskToken must have an expression."); - const node = createBaseExpression(SyntaxKind.YieldExpression); + const node = createBaseNode(SyntaxKind.YieldExpression); node.expression = expression && parenthesizerRules().parenthesizeExpressionForDisallowedComma(expression); node.asteriskToken = asteriskToken; node.transformFlags |= @@ -3556,7 +3539,7 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode // @api function createSpreadElement(expression: Expression) { - const node = createBaseExpression(SyntaxKind.SpreadElement); + const node = createBaseNode(SyntaxKind.SpreadElement); node.expression = parenthesizerRules().parenthesizeExpressionForDisallowedComma(expression); node.transformFlags |= propagateChildFlags(node.expression) | @@ -3580,15 +3563,23 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode heritageClauses: readonly HeritageClause[] | undefined, members: readonly ClassElement[] ) { - const node = createBaseClassLikeDeclaration( - SyntaxKind.ClassExpression, - modifiers, - name, - typeParameters, - heritageClauses, - members - ); - node.transformFlags |= TransformFlags.ContainsES2015; + const node = createBaseDeclaration(SyntaxKind.ClassExpression); + node.modifiers = asNodeArray(modifiers); + node.name = asName(name); + node.typeParameters = asNodeArray(typeParameters); + node.heritageClauses = asNodeArray(heritageClauses); + node.members = createNodeArray(members); + node.transformFlags |= + propagateChildrenFlags(node.modifiers) | + propagateNameFlags(node.name) | + propagateChildrenFlags(node.typeParameters) | + propagateChildrenFlags(node.heritageClauses) | + propagateChildrenFlags(node.members) | + (node.typeParameters ? TransformFlags.ContainsTypeScript : TransformFlags.None) | + TransformFlags.ContainsES2015; + + node.jsDoc = undefined; // initialized by parser (JsDocContainer) + node.jsDocCache = undefined; // initialized by parser (JsDocContainer) return node; } @@ -3612,7 +3603,7 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode // @api function createOmittedExpression() { - return createBaseExpression(SyntaxKind.OmittedExpression); + return createBaseNode(SyntaxKind.OmittedExpression); } // @api @@ -3637,7 +3628,7 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode // @api function createAsExpression(expression: Expression, type: TypeNode) { - const node = createBaseExpression(SyntaxKind.AsExpression); + const node = createBaseNode(SyntaxKind.AsExpression); node.expression = expression; node.type = type; node.transformFlags |= @@ -3657,7 +3648,7 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode // @api function createNonNullExpression(expression: Expression) { - const node = createBaseExpression(SyntaxKind.NonNullExpression); + const node = createBaseNode(SyntaxKind.NonNullExpression); node.expression = parenthesizerRules().parenthesizeLeftSideOfAccess(expression, /*optionalChain*/ false); node.transformFlags |= propagateChildFlags(node.expression) | @@ -3677,7 +3668,7 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode // @api function createSatisfiesExpression(expression: Expression, type: TypeNode) { - const node = createBaseExpression(SyntaxKind.SatisfiesExpression); + const node = createBaseNode(SyntaxKind.SatisfiesExpression); node.expression = expression; node.type = type; node.transformFlags |= @@ -3697,7 +3688,7 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode // @api function createNonNullChain(expression: Expression) { - const node = createBaseExpression(SyntaxKind.NonNullExpression); + const node = createBaseNode(SyntaxKind.NonNullExpression); node.flags |= NodeFlags.OptionalChain; node.expression = parenthesizerRules().parenthesizeLeftSideOfAccess(expression, /*optionalChain*/ true); node.transformFlags |= @@ -3716,7 +3707,7 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode // @api function createMetaProperty(keywordToken: MetaProperty["keywordToken"], name: Identifier) { - const node = createBaseExpression(SyntaxKind.MetaProperty); + const node = createBaseNode(SyntaxKind.MetaProperty); node.keywordToken = keywordToken; node.name = name; node.transformFlags |= propagateChildFlags(node.name); @@ -3730,6 +3721,8 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode default: return Debug.assertNever(keywordToken); } + + node.flowNode = undefined; // initialized by binder (FlowContainer) return node; } @@ -3781,6 +3774,11 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode node.statements = createNodeArray(statements); node.multiLine = multiLine; node.transformFlags |= propagateChildrenFlags(node.statements); + + node.jsDoc = undefined; // initialized by parser (JsDocContainer) + node.jsDocCache = undefined; // initialized by parser (JsDocContainer) + node.locals = undefined; // initialized by binder (LocalsContainer) + node.nextContainer = undefined; // initialized by binder (LocalsContainer) return node; } @@ -3793,7 +3791,7 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode // @api function createVariableStatement(modifiers: readonly Modifier[] | undefined, declarationList: VariableDeclarationList | readonly VariableDeclaration[]) { - const node = createBaseDeclaration(SyntaxKind.VariableStatement); + const node = createBaseNode(SyntaxKind.VariableStatement); node.modifiers = asNodeArray(modifiers); node.declarationList = isArray(declarationList) ? createVariableDeclarationList(declarationList) : declarationList; node.transformFlags |= @@ -3802,6 +3800,11 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode if (modifiersToFlags(node.modifiers) & ModifierFlags.Ambient) { node.transformFlags = TransformFlags.ContainsTypeScript; } + + node.illegalDecorators = undefined; // initialized by parser for grammar errors + node.jsDoc = undefined; // initialized by parser (JsDocContainer) + node.jsDocCache = undefined; // initialized by parser (JsDocContainer) + node.flowNode = undefined; // initialized by binder (FlowContainer) return node; } @@ -3815,7 +3818,10 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode // @api function createEmptyStatement() { - return createBaseNode(SyntaxKind.EmptyStatement); + const node = createBaseNode(SyntaxKind.EmptyStatement); + node.jsDoc = undefined; // initialized by parser (JsDocContainer) + node.jsDocCache = undefined; // initialized by parser (JsDocContainer) + return node; } // @api @@ -3823,6 +3829,10 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode const node = createBaseNode(SyntaxKind.ExpressionStatement); node.expression = parenthesizerRules().parenthesizeExpressionOfExpressionStatement(expression); node.transformFlags |= propagateChildFlags(node.expression); + + node.jsDoc = undefined; // initialized by parser (JsDocContainer) + node.jsDocCache = undefined; // initialized by parser (JsDocContainer) + node.flowNode = undefined; // initialized by binder (FlowContainer) return node; } @@ -3843,6 +3853,10 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode propagateChildFlags(node.expression) | propagateChildFlags(node.thenStatement) | propagateChildFlags(node.elseStatement); + + node.jsDoc = undefined; // initialized by parser (JsDocContainer) + node.jsDocCache = undefined; // initialized by parser (JsDocContainer) + node.flowNode = undefined; // initialized by binder (FlowContainer) return node; } @@ -3863,6 +3877,10 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode node.transformFlags |= propagateChildFlags(node.statement) | propagateChildFlags(node.expression); + + node.jsDoc = undefined; // initialized by parser (JsDocContainer) + node.jsDocCache = undefined; // initialized by parser (JsDocContainer) + node.flowNode = undefined; // initialized by binder (FlowContainer) return node; } @@ -3882,6 +3900,10 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode node.transformFlags |= propagateChildFlags(node.expression) | propagateChildFlags(node.statement); + + node.jsDoc = undefined; // initialized by parser (JsDocContainer) + node.jsDocCache = undefined; // initialized by parser (JsDocContainer) + node.flowNode = undefined; // initialized by binder (FlowContainer) return node; } @@ -3905,6 +3927,12 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode propagateChildFlags(node.condition) | propagateChildFlags(node.incrementor) | propagateChildFlags(node.statement); + + node.jsDoc = undefined; // initialized by parser (JsDocContainer) + node.jsDocCache = undefined; // initialized by parser (JsDocContainer) + node.locals = undefined; // initialized by binder (LocalsContainer) + node.nextContainer = undefined; // initialized by binder (LocalsContainer) + node.flowNode = undefined; // initialized by binder (FlowContainer) return node; } @@ -3928,6 +3956,12 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode propagateChildFlags(node.initializer) | propagateChildFlags(node.expression) | propagateChildFlags(node.statement); + + node.jsDoc = undefined; // initialized by parser (JsDocContainer) + node.jsDocCache = undefined; // initialized by parser (JsDocContainer) + node.locals = undefined; // initialized by binder (LocalsContainer) + node.nextContainer = undefined; // initialized by binder (LocalsContainer) + node.flowNode = undefined; // initialized by binder (FlowContainer) return node; } @@ -3954,6 +3988,12 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode propagateChildFlags(node.statement) | TransformFlags.ContainsES2015; if (awaitModifier) node.transformFlags |= TransformFlags.ContainsES2018; + + node.jsDoc = undefined; // initialized by parser (JsDocContainer) + node.jsDocCache = undefined; // initialized by parser (JsDocContainer) + node.locals = undefined; // initialized by binder (LocalsContainer) + node.nextContainer = undefined; // initialized by binder (LocalsContainer) + node.flowNode = undefined; // initialized by binder (FlowContainer) return node; } @@ -3974,6 +4014,10 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode node.transformFlags |= propagateChildFlags(node.label) | TransformFlags.ContainsHoistedDeclarationOrCompletion; + + node.jsDoc = undefined; // initialized by parser (JsDocContainer) + node.jsDocCache = undefined; // initialized by parser (JsDocContainer) + node.flowNode = undefined; // initialized by binder (FlowContainer) return node; } @@ -3991,6 +4035,10 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode node.transformFlags |= propagateChildFlags(node.label) | TransformFlags.ContainsHoistedDeclarationOrCompletion; + + node.jsDoc = undefined; // initialized by parser (JsDocContainer) + node.jsDocCache = undefined; // initialized by parser (JsDocContainer) + node.flowNode = undefined; // initialized by binder (FlowContainer) return node; } @@ -4010,6 +4058,10 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode propagateChildFlags(node.expression) | TransformFlags.ContainsES2018 | TransformFlags.ContainsHoistedDeclarationOrCompletion; + + node.jsDoc = undefined; // initialized by parser (JsDocContainer) + node.jsDocCache = undefined; // initialized by parser (JsDocContainer) + node.flowNode = undefined; // initialized by binder (FlowContainer) return node; } @@ -4028,6 +4080,10 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode node.transformFlags |= propagateChildFlags(node.expression) | propagateChildFlags(node.statement); + + node.jsDoc = undefined; // initialized by parser (JsDocContainer) + node.jsDocCache = undefined; // initialized by parser (JsDocContainer) + node.flowNode = undefined; // initialized by binder (FlowContainer) return node; } @@ -4047,6 +4103,11 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode node.transformFlags |= propagateChildFlags(node.expression) | propagateChildFlags(node.caseBlock); + + node.jsDoc = undefined; // initialized by parser (JsDocContainer) + node.jsDocCache = undefined; // initialized by parser (JsDocContainer) + node.flowNode = undefined; // initialized by binder (FlowContainer) + node.possiblyExhaustive = false; // initialized by binder return node; } @@ -4066,6 +4127,10 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode node.transformFlags |= propagateChildFlags(node.label) | propagateChildFlags(node.statement); + + node.jsDoc = undefined; // initialized by parser (JsDocContainer) + node.jsDocCache = undefined; // initialized by parser (JsDocContainer) + node.flowNode = undefined; // initialized by binder (FlowContainer) return node; } @@ -4082,6 +4147,10 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode const node = createBaseNode(SyntaxKind.ThrowStatement); node.expression = expression; node.transformFlags |= propagateChildFlags(node.expression); + + node.jsDoc = undefined; // initialized by parser (JsDocContainer) + node.jsDocCache = undefined; // initialized by parser (JsDocContainer) + node.flowNode = undefined; // initialized by binder (FlowContainer) return node; } @@ -4102,6 +4171,10 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode propagateChildFlags(node.tryBlock) | propagateChildFlags(node.catchClause) | propagateChildFlags(node.finallyBlock); + + node.jsDoc = undefined; // initialized by parser (JsDocContainer) + node.jsDocCache = undefined; // initialized by parser (JsDocContainer) + node.flowNode = undefined; // initialized by binder (FlowContainer) return node; } @@ -4116,23 +4189,28 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode // @api function createDebuggerStatement() { - return createBaseNode(SyntaxKind.DebuggerStatement); + const node = createBaseNode(SyntaxKind.DebuggerStatement); + + node.jsDoc = undefined; // initialized by parser (JsDocContainer) + node.jsDocCache = undefined; // initialized by parser (JsDocContainer) + node.flowNode = undefined; // initialized by binder (FlowContainer) + return node; } // @api function createVariableDeclaration(name: string | BindingName, exclamationToken: ExclamationToken | undefined, type: TypeNode | undefined, initializer: Expression | undefined) { - const node = createBaseVariableLikeDeclaration( - SyntaxKind.VariableDeclaration, - /*modifiers*/ undefined, - name, - type, - initializer && parenthesizerRules().parenthesizeExpressionForDisallowedComma(initializer) - ); + const node = createBaseDeclaration(SyntaxKind.VariableDeclaration); + node.name = asName(name); node.exclamationToken = exclamationToken; - node.transformFlags |= propagateChildFlags(node.exclamationToken); - if (exclamationToken) { - node.transformFlags |= TransformFlags.ContainsTypeScript; - } + node.type = type; + node.initializer = asInitializer(initializer); + node.transformFlags |= + propagateNameFlags(node.name) | + propagateChildFlags(node.initializer) | + (node.exclamationToken ?? node.type ? TransformFlags.ContainsTypeScript : TransformFlags.None); + + node.jsDoc = undefined; // initialized by parser (JsDocContainer) + node.jsDocCache = undefined; // initialized by parser (JsDocContainer) return node; } @@ -4171,7 +4249,7 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode // @api function createFunctionDeclaration( - modifiers: readonly ModifierLike[] | undefined, + modifiers: readonly Modifier[] | undefined, asteriskToken: AsteriskToken | undefined, name: string | Identifier | undefined, typeParameters: readonly TypeParameterDeclaration[] | undefined, @@ -4179,45 +4257,55 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode type: TypeNode | undefined, body: Block | undefined ) { - const node = createBaseFunctionLikeDeclaration( - SyntaxKind.FunctionDeclaration, - modifiers, - name, - typeParameters, - parameters, - type, - body - ); + const node = createBaseDeclaration(SyntaxKind.FunctionDeclaration); + node.modifiers = asNodeArray(modifiers); node.asteriskToken = asteriskToken; + node.name = asName(name); + node.typeParameters = asNodeArray(typeParameters); + node.parameters = createNodeArray(parameters); + node.type = type; + node.body = body; + if (!node.body || modifiersToFlags(node.modifiers) & ModifierFlags.Ambient) { node.transformFlags = TransformFlags.ContainsTypeScript; } else { - node.transformFlags |= + const isAsync = modifiersToFlags(node.modifiers) & ModifierFlags.Async; + const isGenerator = !!node.asteriskToken; + const isAsyncGenerator = isAsync && isGenerator; + + node.transformFlags = + propagateChildrenFlags(node.modifiers) | propagateChildFlags(node.asteriskToken) | + propagateNameFlags(node.name) | + propagateChildrenFlags(node.typeParameters) | + propagateChildrenFlags(node.parameters) | + propagateChildFlags(node.type) | + (propagateChildFlags(node.body) & ~TransformFlags.ContainsPossibleTopLevelAwait) | + (isAsyncGenerator ? TransformFlags.ContainsES2018 : + isAsync ? TransformFlags.ContainsES2017 : + isGenerator ? TransformFlags.ContainsGenerator : + TransformFlags.None) | + (node.typeParameters || node.type ? TransformFlags.ContainsTypeScript : TransformFlags.None) | TransformFlags.ContainsHoistedDeclarationOrCompletion; - if (modifiersToFlags(node.modifiers) & ModifierFlags.Async) { - if (node.asteriskToken) { - node.transformFlags |= TransformFlags.ContainsES2018; - } - else { - node.transformFlags |= TransformFlags.ContainsES2017; - } - } - else if (node.asteriskToken) { - node.transformFlags |= TransformFlags.ContainsGenerator; - } } - // The following properties are used only to report grammar errors - node.illegalDecorators = undefined; + node.illegalDecorators = undefined; // initialized by parser for grammar errors + + node.typeArguments = undefined; // used in quick info + node.jsDoc = undefined; // initialized by parser (JsDocContainer) + node.jsDocCache = undefined; // initialized by parser (JsDocContainer) + node.locals = undefined; // initialized by binder (LocalsContainer) + node.nextContainer = undefined; // initialized by binder (LocalsContainer) + node.endFlowNode = undefined; + node.returnFlowNode = undefined; return node; } // @api function updateFunctionDeclaration( node: FunctionDeclaration, - modifiers: readonly ModifierLike[] | undefined, + modifiers: readonly Modifier[] | undefined, asteriskToken: AsteriskToken | undefined, name: Identifier | undefined, typeParameters: readonly TypeParameterDeclaration[] | undefined, @@ -4252,23 +4340,32 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode heritageClauses: readonly HeritageClause[] | undefined, members: readonly ClassElement[] ) { - const node = createBaseClassLikeDeclaration( - SyntaxKind.ClassDeclaration, - modifiers, - name, - typeParameters, - heritageClauses, - members - ); + const node = createBaseDeclaration(SyntaxKind.ClassDeclaration); + node.modifiers = asNodeArray(modifiers); + node.name = asName(name); + node.typeParameters = asNodeArray(typeParameters); + node.heritageClauses = asNodeArray(heritageClauses); + node.members = createNodeArray(members); + if (modifiersToFlags(node.modifiers) & ModifierFlags.Ambient) { node.transformFlags = TransformFlags.ContainsTypeScript; } else { - node.transformFlags |= TransformFlags.ContainsES2015; + node.transformFlags |= + propagateChildrenFlags(node.modifiers) | + propagateNameFlags(node.name) | + propagateChildrenFlags(node.typeParameters) | + propagateChildrenFlags(node.heritageClauses) | + propagateChildrenFlags(node.members) | + (node.typeParameters ? TransformFlags.ContainsTypeScript : TransformFlags.None) | + TransformFlags.ContainsES2015; if (node.transformFlags & TransformFlags.ContainsTypeScriptClassSyntax) { node.transformFlags |= TransformFlags.ContainsTypeScript; } } + + node.jsDoc = undefined; // initialized by parser (JsDocContainer) + node.jsDocCache = undefined; // initialized by parser (JsDocContainer) return node; } @@ -4298,18 +4395,17 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode heritageClauses: readonly HeritageClause[] | undefined, members: readonly TypeElement[] ) { - const node = createBaseInterfaceOrClassLikeDeclaration( - SyntaxKind.InterfaceDeclaration, - modifiers, - name, - typeParameters, - heritageClauses - ); + const node = createBaseDeclaration(SyntaxKind.InterfaceDeclaration); + node.modifiers = asNodeArray(modifiers); + node.name = asName(name); + node.typeParameters = asNodeArray(typeParameters); + node.heritageClauses = asNodeArray(heritageClauses); node.members = createNodeArray(members); node.transformFlags = TransformFlags.ContainsTypeScript; - // The following properties are used only to report grammar errors - node.illegalDecorators = undefined; + node.illegalDecorators = undefined; // initialized by parser for grammar errors + node.jsDoc = undefined; // initialized by parser (JsDocContainer) + node.jsDocCache = undefined; // initialized by parser (JsDocContainer) return node; } @@ -4345,17 +4441,18 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode typeParameters: readonly TypeParameterDeclaration[] | undefined, type: TypeNode ) { - const node = createBaseGenericNamedDeclaration( - SyntaxKind.TypeAliasDeclaration, - modifiers, - name, - typeParameters - ); + const node = createBaseDeclaration(SyntaxKind.TypeAliasDeclaration); + node.modifiers = asNodeArray(modifiers); + node.name = asName(name); + node.typeParameters = asNodeArray(typeParameters); node.type = type; node.transformFlags = TransformFlags.ContainsTypeScript; - // The following properties are used only to report grammar errors - node.illegalDecorators = undefined; + node.illegalDecorators = undefined; // initialized by parser for grammar errors + node.jsDoc = undefined; // initialized by parser (JsDocContainer) + node.jsDocCache = undefined; // initialized by parser (JsDocContainer) + node.locals = undefined; // initialized by binder (LocalsContainer) + node.nextContainer = undefined; // initialized by binder (LocalsContainer) return node; } @@ -4388,19 +4485,20 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode name: string | Identifier, members: readonly EnumMember[] ) { - const node = createBaseNamedDeclaration( - SyntaxKind.EnumDeclaration, - modifiers, - name - ); + const node = createBaseDeclaration(SyntaxKind.EnumDeclaration); + node.modifiers = asNodeArray(modifiers); + node.name = asName(name); node.members = createNodeArray(members); node.transformFlags |= + propagateChildrenFlags(node.modifiers) | + propagateChildFlags(node.name) | propagateChildrenFlags(node.members) | TransformFlags.ContainsTypeScript; node.transformFlags &= ~TransformFlags.ContainsPossibleTopLevelAwait; // Enum declarations cannot contain `await` - // The following properties are used only to report grammar errors - node.illegalDecorators = undefined; + node.illegalDecorators = undefined; // initialized by parser for grammar errors + node.jsDoc = undefined; // initialized by parser (JsDocContainer) + node.jsDocCache = undefined; // initialized by parser (JsDocContainer) return node; } @@ -4448,8 +4546,11 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode } node.transformFlags &= ~TransformFlags.ContainsPossibleTopLevelAwait; // Module declarations cannot contain `await`. - // The following properties are used only to report grammar errors - node.illegalDecorators = undefined; + node.illegalDecorators = undefined; // initialized by parser for grammar errors + node.jsDoc = undefined; // initialized by parser (JsDocContainer) + node.jsDocCache = undefined; // initialized by parser (JsDocContainer) + node.locals = undefined; // initialized by binder (LocalsContainer) + node.nextContainer = undefined; // initialized by binder (LocalsContainer) return node; } @@ -4479,6 +4580,9 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode const node = createBaseNode(SyntaxKind.ModuleBlock); node.statements = createNodeArray(statements); node.transformFlags |= propagateChildrenFlags(node.statements); + + node.jsDoc = undefined; // initialized by parser (JsDocContainer) + node.jsDocCache = undefined; // initialized by parser (JsDocContainer) return node; } @@ -4494,6 +4598,9 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode const node = createBaseNode(SyntaxKind.CaseBlock); node.clauses = createNodeArray(clauses); node.transformFlags |= propagateChildrenFlags(node.clauses); + + node.locals = undefined; // initialized by binder (LocalsContainer) + node.nextContainer = undefined; // initialized by binder (LocalsContainer) return node; } @@ -4506,16 +4613,16 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode // @api function createNamespaceExportDeclaration(name: string | Identifier) { - const node = createBaseNamedDeclaration( - SyntaxKind.NamespaceExportDeclaration, - /*modifiers*/ undefined, - name - ); - node.transformFlags = TransformFlags.ContainsTypeScript; + const node = createBaseDeclaration(SyntaxKind.NamespaceExportDeclaration); + node.name = asName(name); + node.transformFlags |= + propagateIdentifierNameFlags(node.name) | + TransformFlags.ContainsTypeScript; - // The following properties are used only to report grammar errors - node.illegalDecorators = undefined; - node.modifiers = undefined; + node.illegalDecorators = undefined; // initialized by parser to report grammar errors + node.modifiers = undefined; // initialized by parser to report grammar errors + node.jsDoc = undefined; // initialized by parser (JsDocContainer) + node.jsDocCache = undefined; // initialized by parser (JsDocContainer) return node; } @@ -4541,19 +4648,25 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode name: string | Identifier, moduleReference: ModuleReference ) { - const node = createBaseNamedDeclaration( - SyntaxKind.ImportEqualsDeclaration, - modifiers, - name - ); + const node = createBaseDeclaration(SyntaxKind.ImportEqualsDeclaration); + node.modifiers = asNodeArray(modifiers); + node.name = asName(name); node.isTypeOnly = isTypeOnly; node.moduleReference = moduleReference; - node.transformFlags |= propagateChildFlags(node.moduleReference); - if (!isExternalModuleReference(node.moduleReference)) node.transformFlags |= TransformFlags.ContainsTypeScript; + node.transformFlags |= + propagateChildrenFlags(node.modifiers) | + propagateIdentifierNameFlags(node.name) | + propagateChildFlags(node.moduleReference); + + if (!isExternalModuleReference(node.moduleReference)) { + node.transformFlags |= TransformFlags.ContainsTypeScript; + } + node.transformFlags &= ~TransformFlags.ContainsPossibleTopLevelAwait; // Import= declaration is always parsed in an Await context - // The following properties are used only to report grammar errors - node.illegalDecorators = undefined; + node.illegalDecorators = undefined; // initialized by parser to report grammar errors + node.jsDoc = undefined; // initialized by parser (JsDocContainer) + node.jsDocCache = undefined; // initialized by parser (JsDocContainer) return node; } @@ -4587,7 +4700,7 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode moduleSpecifier: Expression, assertClause: AssertClause | undefined ): ImportDeclaration { - const node = createBaseDeclaration(SyntaxKind.ImportDeclaration); + const node = createBaseNode(SyntaxKind.ImportDeclaration); node.modifiers = asNodeArray(modifiers); node.importClause = importClause; node.moduleSpecifier = moduleSpecifier; @@ -4597,8 +4710,9 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode propagateChildFlags(node.moduleSpecifier); node.transformFlags &= ~TransformFlags.ContainsPossibleTopLevelAwait; // always parsed in an Await context - // The following properties are used only to report grammar errors - node.illegalDecorators = undefined; + node.illegalDecorators = undefined; // initialized by parser to report grammar errors + node.jsDoc = undefined; // initialized by parser (JsDocContainer) + node.jsDocCache = undefined; // initialized by parser (JsDocContainer) return node; } @@ -4627,7 +4741,7 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode // @api function createImportClause(isTypeOnly: boolean, name: Identifier | undefined, namedBindings: NamedImportBindings | undefined): ImportClause { - const node = createBaseNode(SyntaxKind.ImportClause); + const node = createBaseDeclaration(SyntaxKind.ImportClause); node.isTypeOnly = isTypeOnly; node.name = name; node.namedBindings = namedBindings; @@ -4702,7 +4816,7 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode // @api function createNamespaceImport(name: Identifier): NamespaceImport { - const node = createBaseNode(SyntaxKind.NamespaceImport); + const node = createBaseDeclaration(SyntaxKind.NamespaceImport); node.name = name; node.transformFlags |= propagateChildFlags(node.name); node.transformFlags &= ~TransformFlags.ContainsPossibleTopLevelAwait; // always parsed in an Await context @@ -4718,7 +4832,7 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode // @api function createNamespaceExport(name: Identifier): NamespaceExport { - const node = createBaseNode(SyntaxKind.NamespaceExport); + const node = createBaseDeclaration(SyntaxKind.NamespaceExport); node.name = name; node.transformFlags |= propagateChildFlags(node.name) | @@ -4752,7 +4866,7 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode // @api function createImportSpecifier(isTypeOnly: boolean, propertyName: Identifier | undefined, name: Identifier) { - const node = createBaseNode(SyntaxKind.ImportSpecifier); + const node = createBaseDeclaration(SyntaxKind.ImportSpecifier); node.isTypeOnly = isTypeOnly; node.propertyName = propertyName; node.name = name; @@ -4787,8 +4901,9 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode node.transformFlags |= propagateChildrenFlags(node.modifiers) | propagateChildFlags(node.expression); node.transformFlags &= ~TransformFlags.ContainsPossibleTopLevelAwait; // always parsed in an Await context - // The following properties are used only to report grammar errors - node.illegalDecorators = undefined; + node.illegalDecorators = undefined; // initialized by parser to report grammar errors + node.jsDoc = undefined; // initialized by parser (JsDocContainer) + node.jsDocCache = undefined; // initialized by parser (JsDocContainer) return node; } @@ -4831,8 +4946,9 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode propagateChildFlags(node.moduleSpecifier); node.transformFlags &= ~TransformFlags.ContainsPossibleTopLevelAwait; // always parsed in an Await context - // The following properties are used only to report grammar errors - node.illegalDecorators = undefined; + node.illegalDecorators = undefined; // initialized by parser to report grammar errors + node.jsDoc = undefined; // initialized by parser (JsDocContainer) + node.jsDocCache = undefined; // initialized by parser (JsDocContainer) return node; } @@ -4887,6 +5003,9 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode propagateChildFlags(node.propertyName) | propagateChildFlags(node.name); node.transformFlags &= ~TransformFlags.ContainsPossibleTopLevelAwait; // always parsed in an Await context + + node.jsDoc = undefined; // initialized by parser (JsDocContainer) + node.jsDocCache = undefined; // initialized by parser (JsDocContainer) return node; } @@ -4902,6 +5021,9 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode // @api function createMissingDeclaration(): MissingDeclaration { const node = createBaseDeclaration(SyntaxKind.MissingDeclaration); + + node.jsDoc = undefined; // initialized by parser (JsDocContainer) + node.jsDocCache = undefined; // initialized by parser (JsDocContainer) return node; } @@ -4979,14 +5101,18 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode // @api function createJSDocFunctionType(parameters: readonly ParameterDeclaration[], type: TypeNode | undefined): JSDocFunctionType { - const node = createBaseSignatureDeclaration( - SyntaxKind.JSDocFunctionType, - /*modifiers*/ undefined, - /*name*/ undefined, - /*typeParameters*/ undefined, - parameters, - type - ); + const node = createBaseDeclaration(SyntaxKind.JSDocFunctionType); + node.parameters = asNodeArray(parameters); + node.type = type; + node.transformFlags = + propagateChildrenFlags(node.parameters) | + (node.type ? TransformFlags.ContainsTypeScript : TransformFlags.None); + + node.jsDoc = undefined; // initialized by parser (JsDocContainer) + node.jsDocCache = undefined; // initialized by parser (JsDocContainer) + node.locals = undefined; // initialized by binder (LocalsContainer) + node.nextContainer = undefined; // initialized by binder (LocalsContainer) + node.typeArguments = undefined; // used in quick info return node; } @@ -5000,7 +5126,7 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode // @api function createJSDocTypeLiteral(propertyTags?: readonly JSDocPropertyLikeTag[], isArrayType = false): JSDocTypeLiteral { - const node = createBaseNode(SyntaxKind.JSDocTypeLiteral); + const node = createBaseDeclaration(SyntaxKind.JSDocTypeLiteral); node.jsDocPropertyTags = asNodeArray(propertyTags); node.isArrayType = isArrayType; return node; @@ -5030,10 +5156,15 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode // @api function createJSDocSignature(typeParameters: readonly JSDocTemplateTag[] | undefined, parameters: readonly JSDocParameterTag[], type?: JSDocReturnTag): JSDocSignature { - const node = createBaseNode(SyntaxKind.JSDocSignature); + const node = createBaseDeclaration(SyntaxKind.JSDocSignature); node.typeParameters = asNodeArray(typeParameters); node.parameters = createNodeArray(parameters); node.type = type; + + node.jsDoc = undefined; // initialized by parser (JsDocContainer) + node.jsDocCache = undefined; // initialized by parser (JsDocContainer) + node.locals = undefined; // initialized by binder (LocalsContainer) + node.nextContainer = undefined; // initialized by binder (LocalsContainer) return node; } @@ -5061,6 +5192,13 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode return node; } + function createBaseJSDocTagDeclaration(kind: T["kind"], tagName: Identifier, comment: string | NodeArray | undefined) { + const node = createBaseDeclaration(kind); + node.tagName = tagName; + node.comment = comment; + return node; + } + // @api function createJSDocTemplateTag(tagName: Identifier | undefined, constraint: JSDocTypeExpression | undefined, typeParameters: readonly TypeParameterDeclaration[], comment?: string | NodeArray): JSDocTemplateTag { const node = createBaseJSDocTag(SyntaxKind.JSDocTemplateTag, tagName ?? createIdentifier("template"), comment); @@ -5081,10 +5219,13 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode // @api function createJSDocTypedefTag(tagName: Identifier | undefined, typeExpression?: JSDocTypeExpression, fullName?: Identifier | JSDocNamespaceDeclaration, comment?: string | NodeArray): JSDocTypedefTag { - const node = createBaseJSDocTag(SyntaxKind.JSDocTypedefTag, tagName ?? createIdentifier("typedef"), comment); + const node = createBaseJSDocTagDeclaration(SyntaxKind.JSDocTypedefTag, tagName ?? createIdentifier("typedef"), comment); node.typeExpression = typeExpression; node.fullName = fullName; node.name = getJSDocTypeAliasName(fullName); + + node.locals = undefined; // initialized by binder (LocalsContainer) + node.nextContainer = undefined; // initialized by binder (LocalsContainer) return node; } @@ -5100,7 +5241,7 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode // @api function createJSDocParameterTag(tagName: Identifier | undefined, name: EntityName, isBracketed: boolean, typeExpression?: JSDocTypeExpression, isNameFirst?: boolean, comment?: string | NodeArray): JSDocParameterTag { - const node = createBaseJSDocTag(SyntaxKind.JSDocParameterTag, tagName ?? createIdentifier("param"), comment); + const node = createBaseJSDocTagDeclaration(SyntaxKind.JSDocParameterTag, tagName ?? createIdentifier("param"), comment); node.typeExpression = typeExpression; node.name = name; node.isNameFirst = !!isNameFirst; @@ -5122,7 +5263,7 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode // @api function createJSDocPropertyTag(tagName: Identifier | undefined, name: EntityName, isBracketed: boolean, typeExpression?: JSDocTypeExpression, isNameFirst?: boolean, comment?: string | NodeArray): JSDocPropertyTag { - const node = createBaseJSDocTag(SyntaxKind.JSDocPropertyTag, tagName ?? createIdentifier("prop"), comment); + const node = createBaseJSDocTagDeclaration(SyntaxKind.JSDocPropertyTag, tagName ?? createIdentifier("prop"), comment); node.typeExpression = typeExpression; node.name = name; node.isNameFirst = !!isNameFirst; @@ -5144,10 +5285,13 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode // @api function createJSDocCallbackTag(tagName: Identifier | undefined, typeExpression: JSDocSignature, fullName?: Identifier | JSDocNamespaceDeclaration, comment?: string | NodeArray): JSDocCallbackTag { - const node = createBaseJSDocTag(SyntaxKind.JSDocCallbackTag, tagName ?? createIdentifier("callback"), comment); + const node = createBaseJSDocTagDeclaration(SyntaxKind.JSDocCallbackTag, tagName ?? createIdentifier("callback"), comment); node.typeExpression = typeExpression; node.fullName = fullName; node.name = getJSDocTypeAliasName(fullName); + + node.locals = undefined; // initialized by binder (LocalsContainer) + node.nextContainer = undefined; // initialized by binder (LocalsContainer) return node; } @@ -5353,6 +5497,25 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode : node; } + // @api + function createJSDocEnumTag(tagName: Identifier | undefined, typeExpression: JSDocTypeExpression, comment?: string | NodeArray) { + const node = createBaseJSDocTagDeclaration(SyntaxKind.JSDocEnumTag, tagName ?? createIdentifier(getDefaultTagNameForKind(SyntaxKind.JSDocEnumTag)), comment); + node.typeExpression = typeExpression; + + node.locals = undefined; // initialized by binder (LocalsContainer) + node.nextContainer = undefined; // initialized by binder (LocalsContainer) + return node; + } + + // @api + function updateJSDocEnumTag(node: JSDocEnumTag, tagName: Identifier = getDefaultTagName(node), typeExpression: JSDocTypeExpression, comment: string | NodeArray | undefined) { + return node.tagName !== tagName + || node.typeExpression !== typeExpression + || node.comment !== comment + ? update(createJSDocEnumTag(tagName, typeExpression, comment), node) + : node; + } + // @api function createJSDocText(text: string): JSDocText { const node = createBaseNode(SyntaxKind.JSDocText); @@ -5535,7 +5698,7 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode // @api function createJsxAttribute(name: Identifier, initializer: JsxAttributeValue | undefined) { - const node = createBaseNode(SyntaxKind.JsxAttribute); + const node = createBaseDeclaration(SyntaxKind.JsxAttribute); node.name = name; node.initializer = initializer; node.transformFlags |= @@ -5555,7 +5718,7 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode // @api function createJsxAttributes(properties: readonly JsxAttributeLike[]) { - const node = createBaseNode(SyntaxKind.JsxAttributes); + const node = createBaseDeclaration(SyntaxKind.JsxAttributes); node.properties = createNodeArray(properties); node.transformFlags |= propagateChildrenFlags(node.properties) | @@ -5618,6 +5781,9 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode node.transformFlags |= propagateChildFlags(node.expression) | propagateChildrenFlags(node.statements); + + node.jsDoc = undefined; // initialized by parser (JsDocContainer) + node.jsDocCache = undefined; // initialized by parser (JsDocContainer) return node; } @@ -5673,20 +5839,16 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode // @api function createCatchClause(variableDeclaration: string | BindingName | VariableDeclaration | undefined, block: Block) { const node = createBaseNode(SyntaxKind.CatchClause); - if (typeof variableDeclaration === "string" || variableDeclaration && !isVariableDeclaration(variableDeclaration)) { - variableDeclaration = createVariableDeclaration( - variableDeclaration, - /*exclamationToken*/ undefined, - /*type*/ undefined, - /*initializer*/ undefined - ); - } - node.variableDeclaration = variableDeclaration; + node.variableDeclaration = asVariableDeclaration(variableDeclaration); node.block = block; + node.transformFlags |= propagateChildFlags(node.variableDeclaration) | - propagateChildFlags(node.block); - if (!variableDeclaration) node.transformFlags |= TransformFlags.ContainsES2019; + propagateChildFlags(node.block) | + (!variableDeclaration ? TransformFlags.ContainsES2019 : TransformFlags.None); + + node.locals = undefined; // initialized by binder (LocalsContainer) + node.nextContainer = undefined; // initialized by binder (LocalsContainer) return node; } @@ -5704,21 +5866,19 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode // @api function createPropertyAssignment(name: string | PropertyName, initializer: Expression) { - const node = createBaseNamedDeclaration( - SyntaxKind.PropertyAssignment, - /*modifiers*/ undefined, - name - ); + const node = createBaseDeclaration(SyntaxKind.PropertyAssignment); + node.name = asName(name); node.initializer = parenthesizerRules().parenthesizeExpressionForDisallowedComma(initializer); node.transformFlags |= - propagateChildFlags(node.name) | + propagateNameFlags(node.name) | propagateChildFlags(node.initializer); - // The following properties are used only to report grammar errors - node.illegalDecorators = undefined; - node.modifiers = undefined; - node.questionToken = undefined; - node.exclamationToken = undefined; + node.illegalDecorators = undefined; // initialized by parser to report grammar errors + node.modifiers = undefined; // initialized by parser to report grammar errors + node.questionToken = undefined; // initialized by parser to report grammar errors + node.exclamationToken = undefined; // initialized by parser to report grammar errors + node.jsDoc = undefined; // initialized by parser (JsDocContainer) + node.jsDocCache = undefined; // initialized by parser (JsDocContainer) return node; } @@ -5743,22 +5903,21 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode // @api function createShorthandPropertyAssignment(name: string | Identifier, objectAssignmentInitializer?: Expression) { - const node = createBaseNamedDeclaration( - SyntaxKind.ShorthandPropertyAssignment, - /*modifiers*/ undefined, - name - ); + const node = createBaseDeclaration(SyntaxKind.ShorthandPropertyAssignment); + node.name = asName(name); node.objectAssignmentInitializer = objectAssignmentInitializer && parenthesizerRules().parenthesizeExpressionForDisallowedComma(objectAssignmentInitializer); node.transformFlags |= + propagateIdentifierNameFlags(node.name) | propagateChildFlags(node.objectAssignmentInitializer) | TransformFlags.ContainsES2015; - // The following properties are used only to report grammar errors - node.equalsToken = undefined; - node.illegalDecorators = undefined; - node.modifiers = undefined; - node.questionToken = undefined; - node.exclamationToken = undefined; + node.equalsToken = undefined; // initialized by parser to report grammar errors + node.illegalDecorators = undefined; // initialized by parser to report grammar errors + node.modifiers = undefined; // initialized by parser to report grammar errors + node.questionToken = undefined; // initialized by parser to report grammar errors + node.exclamationToken = undefined; // initialized by parser to report grammar errors + node.jsDoc = undefined; // initialized by parser (JsDocContainer) + node.jsDocCache = undefined; // initialized by parser (JsDocContainer) return node; } @@ -5784,12 +5943,15 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode // @api function createSpreadAssignment(expression: Expression) { - const node = createBaseNode(SyntaxKind.SpreadAssignment); + const node = createBaseDeclaration(SyntaxKind.SpreadAssignment); node.expression = parenthesizerRules().parenthesizeExpressionForDisallowedComma(expression); node.transformFlags |= propagateChildFlags(node.expression) | TransformFlags.ContainsES2018 | TransformFlags.ContainsObjectRestOrSpread; + + node.jsDoc = undefined; // initialized by parser (JsDocContainer) + node.jsDocCache = undefined; // initialized by parser (JsDocContainer) return node; } @@ -5806,13 +5968,16 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode // @api function createEnumMember(name: string | PropertyName, initializer?: Expression) { - const node = createBaseNode(SyntaxKind.EnumMember); + const node = createBaseDeclaration(SyntaxKind.EnumMember); node.name = asName(name); node.initializer = initializer && parenthesizerRules().parenthesizeExpressionForDisallowedComma(initializer); node.transformFlags |= propagateChildFlags(node.name) | propagateChildFlags(node.initializer) | TransformFlags.ContainsTypeScript; + + node.jsDoc = undefined; // initialized by parser (JsDocContainer) + node.jsDocCache = undefined; // initialized by parser (JsDocContainer) return node; } @@ -5838,16 +6003,103 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode node.statements = createNodeArray(statements); node.endOfFileToken = endOfFileToken; node.flags |= flags; - node.fileName = ""; node.text = ""; + node.fileName = ""; + node.path = "" as Path; + node.resolvedPath = "" as Path; + node.originalFileName = ""; node.languageVersion = 0; node.languageVariant = 0; node.scriptKind = 0; node.isDeclarationFile = false; node.hasNoDefaultLib = false; + node.transformFlags |= propagateChildrenFlags(node.statements) | propagateChildFlags(node.endOfFileToken); + + node.locals = undefined; // initialized by binder (LocalsContainer) + node.nextContainer = undefined; // initialized by binder (LocalsContainer) + node.endFlowNode = undefined; + + node.nodeCount = 0; + node.identifierCount = 0; + node.symbolCount = 0; + node.parseDiagnostics = undefined!; + node.bindDiagnostics = undefined!; + node.bindSuggestionDiagnostics = undefined; + node.lineMap = undefined!; + node.externalModuleIndicator = undefined; + node.setExternalModuleIndicator = undefined; + node.pragmas = undefined!; + node.checkJsDirective = undefined; + node.referencedFiles = undefined!; + node.typeReferenceDirectives = undefined!; + node.libReferenceDirectives = undefined!; + node.amdDependencies = undefined!; + node.commentDirectives = undefined; + node.identifiers = undefined!; + node.packageJsonLocations = undefined; + node.packageJsonScope = undefined; + node.imports = undefined!; + node.moduleAugmentations = undefined!; + node.ambientModuleNames = undefined!; + node.resolvedModules = undefined; + node.classifiableNames = undefined; + node.impliedNodeFormat = undefined; + return node; + } + + function createRedirectedSourceFile(redirectInfo: RedirectInfo) { + const node: SourceFile = Object.create(redirectInfo.redirectTarget); + Object.defineProperties(node, { + id: { + get(this: SourceFile) { return this.redirectInfo!.redirectTarget.id; }, + set(this: SourceFile, value: SourceFile["id"]) { this.redirectInfo!.redirectTarget.id = value; }, + }, + symbol: { + get(this: SourceFile) { return this.redirectInfo!.redirectTarget.symbol; }, + set(this: SourceFile, value: SourceFile["symbol"]) { this.redirectInfo!.redirectTarget.symbol = value; }, + }, + }); + node.redirectInfo = redirectInfo; + return node; + } + + function cloneRedirectedSourceFile(source: SourceFile) { + const node = createRedirectedSourceFile(source.redirectInfo!) as Mutable; + node.flags |= source.flags & ~NodeFlags.Synthesized; + node.fileName = source.fileName; + node.path = source.path; + node.resolvedPath = source.resolvedPath; + node.originalFileName = source.originalFileName; + node.packageJsonLocations = source.packageJsonLocations; + node.packageJsonScope = source.packageJsonScope; + node.emitNode = undefined; + return node; + } + + function cloneSourceFileWorker(source: SourceFile) { + // TODO: This mechanism for cloning results in megamorphic property reads and writes. In future perf-related + // work, we should consider switching explicit property assignments instead of using `for..in`. + const node = baseFactory.createBaseSourceFileNode(SyntaxKind.SourceFile) as Mutable; + node.flags |= source.flags & ~NodeFlags.Synthesized; + for (const p in source) { + if (hasProperty(node, p) || !hasProperty(source, p)) { + continue; + } + if (p === "emitNode") { + node.emitNode = undefined; + continue; + } + (node as any)[p] = (source as any)[p]; + } + return node; + } + + function cloneSourceFile(source: SourceFile) { + const node = source.redirectInfo ? cloneRedirectedSourceFile(source) : cloneSourceFileWorker(source); + setOriginalNode(node, source); return node; } @@ -5860,14 +6112,8 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode hasNoDefaultLib: boolean, libReferences: readonly FileReference[] ) { - const node = (source.redirectInfo ? Object.create(source.redirectInfo.redirectTarget) : baseFactory.createBaseSourceFileNode(SyntaxKind.SourceFile)) as Mutable; - for (const p in source) { - if (p === "emitNode" || hasProperty(node, p) || !hasProperty(source, p)) continue; - (node as any)[p] = (source as any)[p]; - } - node.flags |= source.flags; + const node = cloneSourceFile(source); node.statements = createNodeArray(statements); - node.endOfFileToken = source.endOfFileToken; node.isDeclarationFile = isDeclarationFile; node.referencedFiles = referencedFiles; node.typeReferenceDirectives = typeReferences; @@ -5876,7 +6122,6 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode node.transformFlags = propagateChildrenFlags(node.statements) | propagateChildFlags(node.endOfFileToken); - node.impliedNodeFormat = source.impliedNodeFormat; return node; } @@ -5905,6 +6150,10 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode const node = createBaseNode(SyntaxKind.Bundle); node.prepends = prepends; node.sourceFiles = sourceFiles; + node.syntheticFileReferences = undefined; + node.syntheticTypeReferences = undefined; + node.syntheticLibReferences = undefined; + node.hasNoDefaultLib = undefined; return node; } @@ -6103,6 +6352,52 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode : node; } + function cloneGeneratedIdentifier(node: GeneratedIdentifier): GeneratedIdentifier { + const clone = createBaseIdentifier(node.escapedText, /*originalKeywordKind*/ undefined) as Mutable; + clone.flags |= node.flags & ~NodeFlags.Synthesized; + clone.autoGenerateFlags = node.autoGenerateFlags; + clone.autoGenerateId = node.autoGenerateId; + clone.autoGeneratePrefix = node.autoGeneratePrefix; + clone.autoGenerateSuffix = node.autoGenerateSuffix; + clone.transformFlags = node.transformFlags; + setOriginalNode(clone, node); + return clone; + } + + function cloneIdentifier(node: Identifier): Identifier { + const clone = createBaseIdentifier(node.escapedText, node.originalKeywordKind); + clone.flags |= node.flags & ~NodeFlags.Synthesized; + clone.typeArguments = node.typeArguments; + clone.hasExtendedUnicodeEscape = node.hasExtendedUnicodeEscape; + clone.jsDoc = node.jsDoc; + clone.jsDocCache = node.jsDocCache; + clone.flowNode = node.flowNode; + clone.symbol = node.symbol; + clone.transformFlags = node.transformFlags; + setOriginalNode(clone, node); + return clone; + } + + function cloneGeneratedPrivateIdentifier(node: GeneratedPrivateIdentifier): GeneratedPrivateIdentifier { + const clone = createBasePrivateIdentifier(node.escapedText) as Mutable; + clone.flags |= node.flags & ~NodeFlags.Synthesized; + clone.autoGenerateFlags = node.autoGenerateFlags; + clone.autoGenerateId = node.autoGenerateId; + clone.autoGeneratePrefix = node.autoGeneratePrefix; + clone.autoGenerateSuffix = node.autoGenerateSuffix; + clone.transformFlags = node.transformFlags; + setOriginalNode(clone, node); + return clone; + } + + function clonePrivateIdentifier(node: PrivateIdentifier): PrivateIdentifier { + const clone = createBasePrivateIdentifier(node.escapedText); + clone.flags |= node.flags & ~NodeFlags.Synthesized; + clone.transformFlags = node.transformFlags; + setOriginalNode(clone, node); + return clone; + } + // @api function cloneNode(node: T): T; function cloneNode(node: T) { @@ -6112,11 +6407,23 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode if (node === undefined) { return node; } + if (isSourceFile(node)) { + return cloneSourceFile(node) as T & SourceFile; + } + if (isGeneratedIdentifier(node)) { + return cloneGeneratedIdentifier(node) as T & GeneratedIdentifier; + } + if (isIdentifier(node)) { + return cloneIdentifier(node) as T & Identifier; + } + if (isGeneratedPrivateIdentifier(node)) { + return cloneGeneratedPrivateIdentifier(node) as T & GeneratedPrivateIdentifier; + } + if (isPrivateIdentifier(node)) { + return clonePrivateIdentifier(node) as T & PrivateIdentifier; + } const clone = - isSourceFile(node) ? baseFactory.createBaseSourceFileNode(SyntaxKind.SourceFile) as T : - isIdentifier(node) ? baseFactory.createBaseIdentifierNode(SyntaxKind.Identifier) as T : - isPrivateIdentifier(node) ? baseFactory.createBasePrivateIdentifierNode(SyntaxKind.PrivateIdentifier) as T : !isNodeKind(node.kind) ? baseFactory.createBaseTokenNode(node.kind) as T : baseFactory.createBaseNode(node.kind) as T; @@ -6826,6 +7133,10 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode value; } + function asInitializer(node: Expression | undefined) { + return node && parenthesizerRules().parenthesizeExpressionForDisallowedComma(node); + } + function asToken(value: TKind | Token): Token { return typeof value === "number" ? createToken(value) : value; } @@ -6835,6 +7146,18 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode function asEmbeddedStatement(statement: T | undefined): T | EmptyStatement | undefined { return statement && isNotEmittedStatement(statement) ? setTextRange(setOriginalNode(createEmptyStatement(), statement), statement) : statement; } + + function asVariableDeclaration(variableDeclaration: string | BindingName | VariableDeclaration | undefined) { + if (typeof variableDeclaration === "string" || variableDeclaration && !isVariableDeclaration(variableDeclaration)) { + return createVariableDeclaration( + variableDeclaration, + /*exclamationToken*/ undefined, + /*type*/ undefined, + /*initializer*/ undefined + ); + } + return variableDeclaration; + } } function updateWithoutOriginal(updated: Mutable, original: T): T { @@ -6928,6 +7251,10 @@ function getCookedText(kind: TemplateLiteralToken["kind"], rawText: string) { return tokenValue; } +function propagateNameFlags(node: PropertyName | BindingPattern | NoSubstitutionTemplateLiteral | undefined) { + return node && isIdentifier(node) ? propagateIdentifierNameFlags(node) : propagateChildFlags(node); +} + function propagateIdentifierNameFlags(node: Identifier) { // An IdentifierName is allowed to be `await` return propagateChildFlags(node) & ~TransformFlags.ContainsPossibleTopLevelAwait; diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index 49faf20bed233..e2ec43aaa0d26 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -3,7 +3,6 @@ import { AccessorDeclaration, addRange, addRelatedInfo, - AmdDependency, append, ArrayBindingElement, ArrayBindingPattern, @@ -29,13 +28,13 @@ import { BreakStatement, CallExpression, CallSignatureDeclaration, + canHaveJSDoc, canHaveModifiers, CaseBlock, CaseClause, CaseOrDefaultClause, CatchClause, CharacterCodes, - CheckJsDirective, ClassDeclaration, ClassElement, ClassExpression, @@ -87,7 +86,6 @@ import { ExpressionWithTypeArguments, ExternalModuleReference, fileExtensionIsOneOf, - FileReference, findIndex, forEach, ForEachChildNodes, @@ -166,7 +164,6 @@ import { JSDocCallbackTag, JSDocClassTag, JSDocComment, - JSDocContainer, JSDocDeprecatedTag, JSDocEnumTag, JSDocFunctionType, @@ -287,6 +284,7 @@ import { PlusToken, PostfixUnaryExpression, PostfixUnaryOperator, + PragmaContext, PragmaDefinition, PragmaKindFlags, PragmaMap, @@ -1641,7 +1639,7 @@ namespace Parser { const statement = factory.createExpressionStatement(expression) as JsonObjectExpressionStatement; finishNode(statement, pos); statements = createNodeArray([statement], pos); - endOfFileToken = parseExpectedToken(SyntaxKind.EndOfFileToken, Diagnostics.Unexpected_token); + endOfFileToken = parseExpectedToken(SyntaxKind.EndOfFileToken, Diagnostics.Unexpected_token) as EndOfFileToken; } // Set source file so that errors will be reported with this file name @@ -3068,9 +3066,9 @@ namespace Parser { return undefined; } - if ((node as JSDocContainer).jsDocCache) { + if (canHaveJSDoc(node) && node.jsDocCache) { // jsDocCache may include tags from parent nodes, which might have been modified. - (node as JSDocContainer).jsDocCache = undefined; + node.jsDocCache = undefined; } return node; @@ -10109,19 +10107,6 @@ export function isDeclarationFileName(fileName: string): boolean { return fileExtensionIsOneOf(fileName, supportedDeclarationExtensions); } -/** @internal */ -export interface PragmaContext { - languageVersion: ScriptTarget; - pragmas?: PragmaMap; - checkJsDirective?: CheckJsDirective; - referencedFiles: FileReference[]; - typeReferenceDirectives: FileReference[]; - libReferenceDirectives: FileReference[]; - amdDependencies: AmdDependency[]; - hasNoDefaultLib?: boolean; - moduleName?: string; -} - function parseResolutionMode(mode: string | undefined, pos: number, end: number, reportDiagnostic: PragmaDiagnosticReporter): ResolutionMode { if (!mode) { return undefined; diff --git a/src/compiler/program.ts b/src/compiler/program.ts index 9af6271a58ad0..5cefcfdda324f 100644 --- a/src/compiler/program.ts +++ b/src/compiler/program.ts @@ -239,6 +239,7 @@ import { ParsedCommandLine, parseIsolatedEntityName, parseJsonSourceFileConfigFileContent, + parseNodeFactory, Path, pathIsAbsolute, pathIsRelative, @@ -3343,26 +3344,15 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg } } - function createRedirectSourceFile(redirectTarget: SourceFile, unredirected: SourceFile, fileName: string, path: Path, resolvedPath: Path, originalFileName: string, sourceFileOptions: CreateSourceFileOptions): SourceFile { - const redirect: SourceFile = Object.create(redirectTarget); + function createRedirectedSourceFile(redirectTarget: SourceFile, unredirected: SourceFile, fileName: string, path: Path, resolvedPath: Path, originalFileName: string, sourceFileOptions: CreateSourceFileOptions): SourceFile { + const redirect = parseNodeFactory.createRedirectedSourceFile({ redirectTarget, unredirected }); redirect.fileName = fileName; redirect.path = path; redirect.resolvedPath = resolvedPath; redirect.originalFileName = originalFileName; - redirect.redirectInfo = { redirectTarget, unredirected }; redirect.packageJsonLocations = sourceFileOptions.packageJsonLocations?.length ? sourceFileOptions.packageJsonLocations : undefined; redirect.packageJsonScope = sourceFileOptions.packageJsonScope; sourceFilesFoundSearchingNodeModules.set(path, currentNodeModulesDepth > 0); - Object.defineProperties(redirect, { - id: { - get(this: SourceFile) { return this.redirectInfo!.redirectTarget.id; }, - set(this: SourceFile, value: SourceFile["id"]) { this.redirectInfo!.redirectTarget.id = value; }, - }, - symbol: { - get(this: SourceFile) { return this.redirectInfo!.redirectTarget.symbol; }, - set(this: SourceFile, value: SourceFile["symbol"]) { this.redirectInfo!.redirectTarget.symbol = value; }, - }, - }); return redirect; } @@ -3494,7 +3484,7 @@ export function createProgram(rootNamesOrOptions: readonly string[] | CreateProg if (fileFromPackageId) { // Some other SourceFile already exists with this package name and version. // Instead of creating a duplicate, just redirect to the existing one. - const dupFile = createRedirectSourceFile(fileFromPackageId, file!, fileName, path, toPath(fileName), originalFileName, sourceFileOptions); + const dupFile = createRedirectedSourceFile(fileFromPackageId, file!, fileName, path, toPath(fileName), originalFileName, sourceFileOptions); redirectTargetsMap.add(fileFromPackageId.path, fileName); addFileToFilesByName(dupFile, path, redirectedPath); addFileIncludeReason(dupFile, reason); diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 12bf22b8af668..773d64df907ae 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -16,6 +16,7 @@ import { ProgramBuildInfo, Push, SymlinkCache, + ThisContainer, } from "./_namespaces/ts"; // branded string type used to store absolute, normalized and canonicalized paths @@ -895,23 +896,66 @@ export interface Node extends ReadonlyTextRange { /** @internal */ modifierFlagsCache: ModifierFlags; /** @internal */ readonly transformFlags: TransformFlags; // Flags for transforms /** @internal */ id?: NodeId; // Unique id (used to look up NodeLinks) - readonly parent: Node; // Parent node (initialized by binding) + readonly parent: Node; // Parent node (initialized by binding) /** @internal */ original?: Node; // The original node if this is an updated node. - /** @internal */ symbol: Symbol; // Symbol declared by node (initialized by binding) - /** @internal */ locals?: SymbolTable; // Locals associated with node (initialized by binding) - /** @internal */ nextContainer?: Node; // Next container in declaration order (initialized by binding) - /** @internal */ localSymbol?: Symbol; // Local symbol declared by node (initialized by binding only for exported nodes) - /** @internal */ flowNode?: FlowNode; // Associated FlowNode (initialized by binding) /** @internal */ emitNode?: EmitNode; // Associated EmitNode (initialized by transforms) - /** @internal */ contextualType?: Type; // Used to temporarily assign a contextual type during overload resolution - /** @internal */ inferenceContext?: InferenceContext; // Inference context for contextual type + // NOTE: `symbol` and `localSymbol` have been moved to `Declaration` + // `locals` and `nextContainer` have been moved to `LocalsContainer` + // `flowNode` has been moved to `FlowContainer` + // see: https://github.com/microsoft/TypeScript/pull/51682 } -export interface JSDocContainer { +export interface JSDocContainer extends Node { + _jsdocContainerBrand: any; /** @internal */ jsDoc?: JSDoc[]; // JSDoc that directly precedes this node /** @internal */ jsDocCache?: readonly JSDocTag[]; // Cache for getJSDocTags } +export interface LocalsContainer extends Node { + _localsContainerBrand: any; + /** @internal */ locals?: SymbolTable; // Locals associated with node (initialized by binding) + /** @internal */ nextContainer?: HasLocals; // Next container in declaration order (initialized by binding) +} + +export interface FlowContainer extends Node { + _flowContainerBrand: any; + /** @internal */ flowNode?: FlowNode; // Associated FlowNode (initialized by binding) +} + +/** @internal */ +export type HasFlowNode = + | Identifier + | ThisExpression + | SuperExpression + | QualifiedName + | MetaProperty + | ElementAccessExpression + | PropertyAccessExpression + | BindingElement + | FunctionExpression + | ArrowFunction + | MethodDeclaration + | GetAccessorDeclaration + | SetAccessorDeclaration + | VariableStatement + | ExpressionStatement + | IfStatement + | DoStatement + | WhileStatement + | ForStatement + | ForInStatement + | ForOfStatement + | ContinueStatement + | BreakStatement + | ReturnStatement + | WithStatement + | SwitchStatement + | LabeledStatement + | ThrowStatement + | TryStatement + | DebuggerStatement + ; + // Ideally, `ForEachChildNodes` and `VisitEachChildNodes` would not differ. // However, `forEachChild` currently processes JSDoc comment syntax and missing declarations more thoroughly. // On the other hand, `visitEachChild` actually processes `Identifier`s (which really *shouldn't* have children, @@ -1104,62 +1148,69 @@ export type HasChildren = ; export type HasJSDoc = - | ParameterDeclaration + | AccessorDeclaration + | ArrowFunction + | BinaryExpression + | Block + | BreakStatement | CallSignatureDeclaration + | CaseClause + | ClassLikeDeclaration | ClassStaticBlockDeclaration + | ConstructorDeclaration + | ConstructorTypeNode | ConstructSignatureDeclaration - | MethodSignature - | PropertySignature - | ArrowFunction - | ParenthesizedExpression - | SpreadAssignment - | ShorthandPropertyAssignment - | PropertyAssignment - | FunctionExpression - | EmptyStatement + | ContinueStatement | DebuggerStatement - | Block - | VariableStatement - | ExpressionStatement - | IfStatement | DoStatement - | WhileStatement - | ForStatement + | ElementAccessExpression + | EmptyStatement + | EndOfFileToken + | EnumDeclaration + | EnumMember + | ExportAssignment + | ExportDeclaration + | ExportSpecifier + | ExpressionStatement | ForInStatement | ForOfStatement - | BreakStatement - | ContinueStatement - | ReturnStatement - | WithStatement - | SwitchStatement - | LabeledStatement - | ThrowStatement - | TryStatement + | ForStatement | FunctionDeclaration - | ConstructorDeclaration - | MethodDeclaration - | VariableDeclaration - | PropertyDeclaration - | AccessorDeclaration - | ClassLikeDeclaration - | InterfaceDeclaration - | TypeAliasDeclaration - | EnumMember - | EnumDeclaration - | ModuleDeclaration - | ImportEqualsDeclaration + | FunctionExpression + | FunctionTypeNode + | Identifier + | IfStatement | ImportDeclaration - | NamespaceExportDeclaration - | ExportAssignment + | ImportEqualsDeclaration | IndexSignatureDeclaration - | FunctionTypeNode - | ConstructorTypeNode + | InterfaceDeclaration | JSDocFunctionType - | ExportDeclaration + | JSDocSignature + | LabeledStatement + | MethodDeclaration + | MethodSignature + | ModuleDeclaration | NamedTupleMember - | ExportSpecifier - | CaseClause - | EndOfFileToken + | NamespaceExportDeclaration + | ObjectLiteralExpression + | ParameterDeclaration + | ParenthesizedExpression + | PropertyAccessExpression + | PropertyAssignment + | PropertyDeclaration + | PropertySignature + | ReturnStatement + | ShorthandPropertyAssignment + | SpreadAssignment + | SwitchStatement + | ThrowStatement + | TryStatement + | TypeAliasDeclaration + | TypeParameterDeclaration + | VariableDeclaration + | VariableStatement + | WhileStatement + | WithStatement ; export type HasType = @@ -1306,6 +1357,191 @@ export type HasIllegalModifiers = | NamespaceExportDeclaration ; +/** + * Declarations that can contain other declarations. Corresponds with `ContainerFlags.IsContainer` in binder.ts. + * + * @internal + */ +export type IsContainer = + | ClassExpression + | ClassDeclaration + | EnumDeclaration + | ObjectLiteralExpression + | TypeLiteralNode + | JSDocTypeLiteral + | JsxAttributes + | InterfaceDeclaration + | ModuleDeclaration + | TypeAliasDeclaration + | MappedTypeNode + | IndexSignatureDeclaration + | SourceFile + | GetAccessorDeclaration + | SetAccessorDeclaration + | MethodDeclaration + | ConstructorDeclaration + | FunctionDeclaration + | MethodSignature + | CallSignatureDeclaration + | JSDocSignature + | JSDocFunctionType + | FunctionTypeNode + | ConstructSignatureDeclaration + | ConstructorTypeNode + | ClassStaticBlockDeclaration + | FunctionExpression + | ArrowFunction + ; + +/** + * Nodes that introduce a new block scope. Corresponds with `ContainerFlags.IsBlockScopedContainer` in binder.ts. + * + * @internal + */ +export type IsBlockScopedContainer = + | IsContainer + | CatchClause + | ForStatement + | ForInStatement + | ForOfStatement + | CaseBlock + | Block + ; + +/** + * Corresponds with `ContainerFlags.IsControlFlowContainer` in binder.ts. + * + * @internal + */ +export type IsControlFlowContainer = + | SourceFile + | GetAccessorDeclaration + | SetAccessorDeclaration + | MethodDeclaration + | ConstructorDeclaration + | FunctionDeclaration + | MethodSignature + | CallSignatureDeclaration + | JSDocSignature + | JSDocFunctionType + | FunctionTypeNode + | ConstructSignatureDeclaration + | ConstructorTypeNode + | ClassStaticBlockDeclaration + | FunctionExpression + | ArrowFunction + | ModuleBlock + | PropertyDeclaration + ; + +/** + * Corresponds with `ContainerFlags.IsFunctionLike` in binder.ts. + * + * @internal + */ +export type IsFunctionLike = + | GetAccessorDeclaration + | SetAccessorDeclaration + | MethodDeclaration + | ConstructorDeclaration + | FunctionDeclaration + | MethodSignature + | CallSignatureDeclaration + | JSDocSignature + | JSDocFunctionType + | FunctionTypeNode + | ConstructSignatureDeclaration + | ConstructorTypeNode + | ClassStaticBlockDeclaration + | FunctionExpression + | ArrowFunction + ; + +/** + * Corresponds with `ContainerFlags.IsFunctionExpression` in binder.ts. + * + * @internal + */ +export type IsFunctionExpression = + | FunctionExpression + | ArrowFunction + ; + +/** + * Nodes that can have local symbols. Corresponds with `ContainerFlags.HasLocals`. Constituents should extend + * {@link LocalsContainer}. + * + * @internal + */ +export type HasLocals = + | ArrowFunction + | Block + | CallSignatureDeclaration + | CaseBlock + | CatchClause + | ClassStaticBlockDeclaration + | ConditionalTypeNode + | ConstructorDeclaration + | ConstructorTypeNode + | ConstructSignatureDeclaration + | ForStatement + | ForInStatement + | ForOfStatement + | FunctionDeclaration + | FunctionExpression + | FunctionTypeNode + | GetAccessorDeclaration + | IndexSignatureDeclaration + | JSDocCallbackTag + | JSDocEnumTag + | JSDocFunctionType + | JSDocSignature + | JSDocTypedefTag + | MappedTypeNode + | MethodDeclaration + | MethodSignature + | ModuleDeclaration + | SetAccessorDeclaration + | SourceFile + | TypeAliasDeclaration + ; + +/** + * Corresponds with `ContainerFlags.IsInterface` in binder.ts. + * + * @internal + */ +export type IsInterface = + | InterfaceDeclaration + ; + +/** + * Corresponds with `ContainerFlags.IsObjectLiteralOrClassExpressionMethodOrAccessor` in binder.ts. + * + * @internal + */ +export type IsObjectLiteralOrClassExpressionMethodOrAccessor = + | GetAccessorDeclaration + | SetAccessorDeclaration + | MethodDeclaration + ; + +/** + * Corresponds with `ContainerFlags` in binder.ts. + * + * @internal + */ +export type HasContainerFlags = + | IsContainer + | IsBlockScopedContainer + | IsControlFlowContainer + | IsFunctionLike + | IsFunctionExpression + | HasLocals + | IsInterface + | IsObjectLiteralOrClassExpressionMethodOrAccessor + ; + /** @internal */ export interface MutableNodeArray extends Array, TextRange { hasTrailingComma: boolean; @@ -1432,7 +1668,7 @@ export const enum GeneratedIdentifierFlags { AllowNameSubstitution = 1 << 6, // Used by `module.ts` to indicate generated nodes which can have substitutions performed upon them (as they were generated by an earlier transform phase) } -export interface Identifier extends PrimaryExpression, Declaration { +export interface Identifier extends PrimaryExpression, Declaration, JSDocContainer, FlowContainer { readonly kind: SyntaxKind.Identifier; /** * Prefer to use `id.unescapedText`. (Note: This is available only in services, not internally to the TypeScript compiler.) @@ -1461,7 +1697,7 @@ export interface GeneratedIdentifier extends Identifier { autoGenerateFlags: GeneratedIdentifierFlags; } -export interface QualifiedName extends Node { +export interface QualifiedName extends Node, FlowContainer { readonly kind: SyntaxKind.QualifiedName; readonly left: EntityName; readonly right: Identifier; @@ -1486,6 +1722,8 @@ export type DeclarationName = export interface Declaration extends Node { _declarationBrand: any; + /** @internal */ symbol: Symbol; // Symbol declared by node (initialized by binding) + /** @internal */ localSymbol?: Symbol; // Local symbol declared by node (initialized by binding only for exported nodes) } export interface NamedDeclaration extends Declaration { @@ -1557,7 +1795,7 @@ export interface Decorator extends Node { readonly expression: LeftHandSideExpression; } -export interface TypeParameterDeclaration extends NamedDeclaration { +export interface TypeParameterDeclaration extends NamedDeclaration, JSDocContainer { readonly kind: SyntaxKind.TypeParameter; readonly parent: DeclarationWithTypeParameterChildren | InferTypeNode; readonly modifiers?: NodeArray; @@ -1594,11 +1832,11 @@ export type SignatureDeclaration = | FunctionExpression | ArrowFunction; -export interface CallSignatureDeclaration extends SignatureDeclarationBase, TypeElement { +export interface CallSignatureDeclaration extends SignatureDeclarationBase, TypeElement, LocalsContainer { readonly kind: SyntaxKind.CallSignature; } -export interface ConstructSignatureDeclaration extends SignatureDeclarationBase, TypeElement { +export interface ConstructSignatureDeclaration extends SignatureDeclarationBase, TypeElement, LocalsContainer { readonly kind: SyntaxKind.ConstructSignature; } @@ -1633,7 +1871,7 @@ export interface ParameterDeclaration extends NamedDeclaration, JSDocContainer { readonly initializer?: Expression; // Optional initializer } -export interface BindingElement extends NamedDeclaration { +export interface BindingElement extends NamedDeclaration, FlowContainer { readonly kind: SyntaxKind.BindingElement; readonly parent: BindingPattern; readonly propertyName?: PropertyName; // Binding property name (in object binding pattern) @@ -1647,6 +1885,7 @@ export type BindingElementGrandparent = BindingElement["parent"]["parent"]; export interface PropertySignature extends TypeElement, JSDocContainer { readonly kind: SyntaxKind.PropertySignature; + readonly parent: TypeLiteralNode | InterfaceDeclaration; readonly modifiers?: NodeArray; readonly name: PropertyName; // Declared property name readonly questionToken?: QuestionToken; // Present on optional property @@ -1766,10 +2005,6 @@ export type VariableLikeDeclaration = | JSDocPropertyTag | JSDocParameterTag; -export interface PropertyLikeDeclaration extends NamedDeclaration { - readonly name: PropertyName; -} - export interface ObjectBindingPattern extends Node { readonly kind: SyntaxKind.ObjectBindingPattern; readonly parent: VariableDeclaration | ParameterDeclaration | BindingElement; @@ -1816,7 +2051,7 @@ export type FunctionLikeDeclaration = /** @deprecated Use SignatureDeclaration */ export type FunctionLike = SignatureDeclaration; -export interface FunctionDeclaration extends FunctionLikeDeclarationBase, DeclarationStatement { +export interface FunctionDeclaration extends FunctionLikeDeclarationBase, DeclarationStatement, LocalsContainer { readonly kind: SyntaxKind.FunctionDeclaration; readonly modifiers?: NodeArray; readonly name?: Identifier; @@ -1826,9 +2061,9 @@ export interface FunctionDeclaration extends FunctionLikeDeclarationBase, Declar /** @internal */ readonly illegalDecorators?: NodeArray | undefined; // functions cannot have decorators } -export interface MethodSignature extends SignatureDeclarationBase, TypeElement { +export interface MethodSignature extends SignatureDeclarationBase, TypeElement, LocalsContainer { readonly kind: SyntaxKind.MethodSignature; - readonly parent: ObjectTypeDeclaration; + readonly parent: TypeLiteralNode | InterfaceDeclaration; readonly modifiers?: NodeArray; readonly name: PropertyName; } @@ -1842,7 +2077,7 @@ export interface MethodSignature extends SignatureDeclarationBase, TypeElement { // Because of this, it may be necessary to determine what sort of MethodDeclaration you have // at later stages of the compiler pipeline. In that case, you can either check the parent kind // of the method, or use helpers like isObjectLiteralMethodDeclaration -export interface MethodDeclaration extends FunctionLikeDeclarationBase, ClassElement, ObjectLiteralElement, JSDocContainer { +export interface MethodDeclaration extends FunctionLikeDeclarationBase, ClassElement, ObjectLiteralElement, JSDocContainer, LocalsContainer, FlowContainer { readonly kind: SyntaxKind.MethodDeclaration; readonly parent: ClassLikeDeclaration | ObjectLiteralExpression; readonly modifiers?: NodeArray | undefined; @@ -1853,7 +2088,7 @@ export interface MethodDeclaration extends FunctionLikeDeclarationBase, ClassEle /** @internal */ readonly exclamationToken?: ExclamationToken | undefined; // A method cannot have an exclamation token } -export interface ConstructorDeclaration extends FunctionLikeDeclarationBase, ClassElement, JSDocContainer { +export interface ConstructorDeclaration extends FunctionLikeDeclarationBase, ClassElement, JSDocContainer, LocalsContainer { readonly kind: SyntaxKind.Constructor; readonly parent: ClassLikeDeclaration; readonly modifiers?: NodeArray | undefined; @@ -1873,7 +2108,7 @@ export interface SemicolonClassElement extends ClassElement { // See the comment on MethodDeclaration for the intuition behind GetAccessorDeclaration being a // ClassElement and an ObjectLiteralElement. -export interface GetAccessorDeclaration extends FunctionLikeDeclarationBase, ClassElement, TypeElement, ObjectLiteralElement, JSDocContainer { +export interface GetAccessorDeclaration extends FunctionLikeDeclarationBase, ClassElement, TypeElement, ObjectLiteralElement, JSDocContainer, LocalsContainer, FlowContainer { readonly kind: SyntaxKind.GetAccessor; readonly parent: ClassLikeDeclaration | ObjectLiteralExpression | TypeLiteralNode | InterfaceDeclaration; readonly modifiers?: NodeArray; @@ -1886,7 +2121,7 @@ export interface GetAccessorDeclaration extends FunctionLikeDeclarationBase, Cla // See the comment on MethodDeclaration for the intuition behind SetAccessorDeclaration being a // ClassElement and an ObjectLiteralElement. -export interface SetAccessorDeclaration extends FunctionLikeDeclarationBase, ClassElement, TypeElement, ObjectLiteralElement, JSDocContainer { +export interface SetAccessorDeclaration extends FunctionLikeDeclarationBase, ClassElement, TypeElement, ObjectLiteralElement, JSDocContainer, LocalsContainer, FlowContainer { readonly kind: SyntaxKind.SetAccessor; readonly parent: ClassLikeDeclaration | ObjectLiteralExpression | TypeLiteralNode | InterfaceDeclaration; readonly modifiers?: NodeArray; @@ -1900,7 +2135,7 @@ export interface SetAccessorDeclaration extends FunctionLikeDeclarationBase, Cla export type AccessorDeclaration = GetAccessorDeclaration | SetAccessorDeclaration; -export interface IndexSignatureDeclaration extends SignatureDeclarationBase, ClassElement, TypeElement { +export interface IndexSignatureDeclaration extends SignatureDeclarationBase, ClassElement, TypeElement, LocalsContainer { readonly kind: SyntaxKind.IndexSignature; readonly parent: ObjectTypeDeclaration; readonly modifiers?: NodeArray; @@ -1910,7 +2145,7 @@ export interface IndexSignatureDeclaration extends SignatureDeclarationBase, Cla /** @internal */ readonly illegalDecorators?: NodeArray | undefined; } -export interface ClassStaticBlockDeclaration extends ClassElement, JSDocContainer { +export interface ClassStaticBlockDeclaration extends ClassElement, JSDocContainer, LocalsContainer { readonly kind: SyntaxKind.ClassStaticBlockDeclaration; readonly parent: ClassDeclaration | ClassExpression; readonly body: Block; @@ -1965,14 +2200,14 @@ export interface FunctionOrConstructorTypeNodeBase extends TypeNode, SignatureDe readonly type: TypeNode; } -export interface FunctionTypeNode extends FunctionOrConstructorTypeNodeBase { +export interface FunctionTypeNode extends FunctionOrConstructorTypeNodeBase, LocalsContainer { readonly kind: SyntaxKind.FunctionType; // The following properties are used only to report grammar errors /** @internal */ readonly modifiers?: NodeArray | undefined; } -export interface ConstructorTypeNode extends FunctionOrConstructorTypeNodeBase { +export interface ConstructorTypeNode extends FunctionOrConstructorTypeNodeBase, LocalsContainer { readonly kind: SyntaxKind.ConstructorType; readonly modifiers?: NodeArray; } @@ -2017,7 +2252,7 @@ export interface TupleTypeNode extends TypeNode { readonly elements: NodeArray; } -export interface NamedTupleMember extends TypeNode, JSDocContainer, Declaration { +export interface NamedTupleMember extends TypeNode, Declaration, JSDocContainer { readonly kind: SyntaxKind.NamedTupleMember; readonly dotDotDotToken?: Token; readonly name: Identifier; @@ -2047,7 +2282,7 @@ export interface IntersectionTypeNode extends TypeNode { readonly types: NodeArray; } -export interface ConditionalTypeNode extends TypeNode { +export interface ConditionalTypeNode extends TypeNode, LocalsContainer { readonly kind: SyntaxKind.ConditionalType; readonly checkType: TypeNode; readonly extendsType: TypeNode; @@ -2082,7 +2317,7 @@ export interface IndexedAccessTypeNode extends TypeNode { readonly indexType: TypeNode; } -export interface MappedTypeNode extends TypeNode, Declaration { +export interface MappedTypeNode extends TypeNode, Declaration, LocalsContainer { readonly kind: SyntaxKind.MappedType; readonly readonlyToken?: ReadonlyKeyword | PlusToken | MinusToken; readonly typeParameter: TypeParameterDeclaration; @@ -2211,11 +2446,11 @@ export interface FalseLiteral extends PrimaryExpression { export type BooleanLiteral = TrueLiteral | FalseLiteral; -export interface ThisExpression extends PrimaryExpression { +export interface ThisExpression extends PrimaryExpression, FlowContainer { readonly kind: SyntaxKind.ThisKeyword; } -export interface SuperExpression extends PrimaryExpression { +export interface SuperExpression extends PrimaryExpression, FlowContainer { readonly kind: SyntaxKind.SuperKeyword; } @@ -2405,7 +2640,7 @@ export type LogicalOrCoalescingAssignmentOperator export type BinaryOperatorToken = Token; -export interface BinaryExpression extends Expression, Declaration { +export interface BinaryExpression extends Expression, Declaration, JSDocContainer { readonly kind: SyntaxKind.BinaryExpression; readonly left: Expression; readonly operatorToken: BinaryOperatorToken; @@ -2500,14 +2735,14 @@ export interface ConditionalExpression extends Expression { export type FunctionBody = Block; export type ConciseBody = FunctionBody | Expression; -export interface FunctionExpression extends PrimaryExpression, FunctionLikeDeclarationBase, JSDocContainer { +export interface FunctionExpression extends PrimaryExpression, FunctionLikeDeclarationBase, JSDocContainer, LocalsContainer, FlowContainer { readonly kind: SyntaxKind.FunctionExpression; readonly modifiers?: NodeArray; readonly name?: Identifier; readonly body: FunctionBody; // Required, whereas the member inherited from FunctionDeclaration is optional } -export interface ArrowFunction extends Expression, FunctionLikeDeclarationBase, JSDocContainer { +export interface ArrowFunction extends Expression, FunctionLikeDeclarationBase, JSDocContainer, LocalsContainer, FlowContainer { readonly kind: SyntaxKind.ArrowFunction; readonly modifiers?: NodeArray; readonly equalsGreaterThanToken: EqualsGreaterThanToken; @@ -2681,7 +2916,7 @@ export interface ObjectLiteralExpressionBase ext } // An ObjectLiteralExpression is the declaration node for an anonymous symbol. -export interface ObjectLiteralExpression extends ObjectLiteralExpressionBase { +export interface ObjectLiteralExpression extends ObjectLiteralExpressionBase, JSDocContainer { readonly kind: SyntaxKind.ObjectLiteralExpression; /** @internal */ multiLine?: boolean; @@ -2691,7 +2926,7 @@ export type EntityNameExpression = Identifier | PropertyAccessEntityNameExpressi export type EntityNameOrEntityNameExpression = EntityName | EntityNameExpression; export type AccessExpression = PropertyAccessExpression | ElementAccessExpression; -export interface PropertyAccessExpression extends MemberExpression, NamedDeclaration { +export interface PropertyAccessExpression extends MemberExpression, NamedDeclaration, JSDocContainer, FlowContainer { readonly kind: SyntaxKind.PropertyAccessExpression; readonly expression: LeftHandSideExpression; readonly questionDotToken?: QuestionDotToken; @@ -2724,7 +2959,7 @@ export interface PropertyAccessEntityNameExpression extends PropertyAccessExpres readonly name: Identifier; } -export interface ElementAccessExpression extends MemberExpression { +export interface ElementAccessExpression extends MemberExpression, Declaration, JSDocContainer, FlowContainer { readonly kind: SyntaxKind.ElementAccessExpression; readonly expression: LeftHandSideExpression; readonly questionDotToken?: QuestionDotToken; @@ -2897,7 +3132,7 @@ export interface NonNullChain extends NonNullExpression { // NOTE: MetaProperty is really a MemberExpression, but we consider it a PrimaryExpression // for the same reasons we treat NewExpression as a PrimaryExpression. -export interface MetaProperty extends PrimaryExpression { +export interface MetaProperty extends PrimaryExpression, FlowContainer { readonly kind: SyntaxKind.MetaProperty; readonly keywordToken: SyntaxKind.NewKeyword | SyntaxKind.ImportKeyword; readonly name: Identifier; @@ -3075,7 +3310,7 @@ export interface EmptyStatement extends Statement { readonly kind: SyntaxKind.EmptyStatement; } -export interface DebuggerStatement extends Statement { +export interface DebuggerStatement extends Statement, FlowContainer { readonly kind: SyntaxKind.DebuggerStatement; } @@ -3095,13 +3330,13 @@ export type BlockLike = | CaseOrDefaultClause ; -export interface Block extends Statement { +export interface Block extends Statement, LocalsContainer { readonly kind: SyntaxKind.Block; readonly statements: NodeArray; /** @internal */ multiLine?: boolean; } -export interface VariableStatement extends Statement { +export interface VariableStatement extends Statement, FlowContainer { readonly kind: SyntaxKind.VariableStatement; readonly modifiers?: NodeArray; readonly declarationList: VariableDeclarationList; @@ -3110,7 +3345,7 @@ export interface VariableStatement extends Statement { /** @internal */ illegalDecorators?: NodeArray | undefined; } -export interface ExpressionStatement extends Statement { +export interface ExpressionStatement extends Statement, FlowContainer { readonly kind: SyntaxKind.ExpressionStatement; readonly expression: Expression; } @@ -3120,7 +3355,7 @@ export interface PrologueDirective extends ExpressionStatement { readonly expression: StringLiteral; } -export interface IfStatement extends Statement { +export interface IfStatement extends Statement, FlowContainer { readonly kind: SyntaxKind.IfStatement; readonly expression: Expression; readonly thenStatement: Statement; @@ -3131,12 +3366,12 @@ export interface IterationStatement extends Statement { readonly statement: Statement; } -export interface DoStatement extends IterationStatement { +export interface DoStatement extends IterationStatement, FlowContainer { readonly kind: SyntaxKind.DoStatement; readonly expression: Expression; } -export interface WhileStatement extends IterationStatement { +export interface WhileStatement extends IterationStatement, FlowContainer { readonly kind: SyntaxKind.WhileStatement; readonly expression: Expression; } @@ -3146,7 +3381,7 @@ export type ForInitializer = | Expression ; -export interface ForStatement extends IterationStatement { +export interface ForStatement extends IterationStatement, LocalsContainer, FlowContainer { readonly kind: SyntaxKind.ForStatement; readonly initializer?: ForInitializer; readonly condition?: Expression; @@ -3158,25 +3393,25 @@ export type ForInOrOfStatement = | ForOfStatement ; -export interface ForInStatement extends IterationStatement { +export interface ForInStatement extends IterationStatement, LocalsContainer, FlowContainer { readonly kind: SyntaxKind.ForInStatement; readonly initializer: ForInitializer; readonly expression: Expression; } -export interface ForOfStatement extends IterationStatement { +export interface ForOfStatement extends IterationStatement, LocalsContainer, FlowContainer { readonly kind: SyntaxKind.ForOfStatement; readonly awaitModifier?: AwaitKeyword; readonly initializer: ForInitializer; readonly expression: Expression; } -export interface BreakStatement extends Statement { +export interface BreakStatement extends Statement, FlowContainer { readonly kind: SyntaxKind.BreakStatement; readonly label?: Identifier; } -export interface ContinueStatement extends Statement { +export interface ContinueStatement extends Statement, FlowContainer { readonly kind: SyntaxKind.ContinueStatement; readonly label?: Identifier; } @@ -3186,25 +3421,25 @@ export type BreakOrContinueStatement = | ContinueStatement ; -export interface ReturnStatement extends Statement { +export interface ReturnStatement extends Statement, FlowContainer { readonly kind: SyntaxKind.ReturnStatement; readonly expression?: Expression; } -export interface WithStatement extends Statement { +export interface WithStatement extends Statement, FlowContainer { readonly kind: SyntaxKind.WithStatement; readonly expression: Expression; readonly statement: Statement; } -export interface SwitchStatement extends Statement { +export interface SwitchStatement extends Statement, FlowContainer { readonly kind: SyntaxKind.SwitchStatement; readonly expression: Expression; readonly caseBlock: CaseBlock; possiblyExhaustive?: boolean; // initialized by binding } -export interface CaseBlock extends Node { +export interface CaseBlock extends Node, LocalsContainer { readonly kind: SyntaxKind.CaseBlock; readonly parent: SwitchStatement; readonly clauses: NodeArray; @@ -3230,25 +3465,25 @@ export type CaseOrDefaultClause = | DefaultClause ; -export interface LabeledStatement extends Statement { +export interface LabeledStatement extends Statement, FlowContainer { readonly kind: SyntaxKind.LabeledStatement; readonly label: Identifier; readonly statement: Statement; } -export interface ThrowStatement extends Statement { +export interface ThrowStatement extends Statement, FlowContainer { readonly kind: SyntaxKind.ThrowStatement; readonly expression: Expression; } -export interface TryStatement extends Statement { +export interface TryStatement extends Statement, FlowContainer { readonly kind: SyntaxKind.TryStatement; readonly tryBlock: Block; readonly catchClause?: CatchClause; readonly finallyBlock?: Block; } -export interface CatchClause extends Node { +export interface CatchClause extends Node, LocalsContainer { readonly kind: SyntaxKind.CatchClause; readonly parent: TryStatement; readonly variableDeclaration?: VariableDeclaration; @@ -3331,7 +3566,7 @@ export interface HeritageClause extends Node { readonly types: NodeArray; } -export interface TypeAliasDeclaration extends DeclarationStatement, JSDocContainer { +export interface TypeAliasDeclaration extends DeclarationStatement, JSDocContainer, LocalsContainer { readonly kind: SyntaxKind.TypeAliasDeclaration; readonly modifiers?: NodeArray; readonly name: Identifier; @@ -3376,7 +3611,7 @@ export interface AmbientModuleDeclaration extends ModuleDeclaration { readonly body?: ModuleBlock; } -export interface ModuleDeclaration extends DeclarationStatement, JSDocContainer { +export interface ModuleDeclaration extends DeclarationStatement, JSDocContainer, LocalsContainer { readonly kind: SyntaxKind.ModuleDeclaration; readonly parent: ModuleBody | SourceFile; readonly modifiers?: NodeArray; @@ -3672,7 +3907,7 @@ export interface JSDocOptionalType extends JSDocType { readonly type: TypeNode; } -export interface JSDocFunctionType extends JSDocType, SignatureDeclarationBase { +export interface JSDocFunctionType extends JSDocType, SignatureDeclarationBase, LocalsContainer { readonly kind: SyntaxKind.JSDocFunctionType; } @@ -3781,7 +4016,7 @@ export interface JSDocOverrideTag extends JSDocTag { readonly kind: SyntaxKind.JSDocOverrideTag; } -export interface JSDocEnumTag extends JSDocTag, Declaration { +export interface JSDocEnumTag extends JSDocTag, Declaration, LocalsContainer { readonly kind: SyntaxKind.JSDocEnumTag; readonly parent: JSDoc; readonly typeExpression: JSDocTypeExpression; @@ -3813,7 +4048,7 @@ export interface JSDocTypeTag extends JSDocTag { readonly typeExpression: JSDocTypeExpression; } -export interface JSDocTypedefTag extends JSDocTag, NamedDeclaration { +export interface JSDocTypedefTag extends JSDocTag, NamedDeclaration, LocalsContainer { readonly kind: SyntaxKind.JSDocTypedefTag; readonly parent: JSDoc; readonly fullName?: JSDocNamespaceDeclaration | Identifier; @@ -3821,7 +4056,7 @@ export interface JSDocTypedefTag extends JSDocTag, NamedDeclaration { readonly typeExpression?: JSDocTypeExpression | JSDocTypeLiteral; } -export interface JSDocCallbackTag extends JSDocTag, NamedDeclaration { +export interface JSDocCallbackTag extends JSDocTag, NamedDeclaration, LocalsContainer { readonly kind: SyntaxKind.JSDocCallbackTag; readonly parent: JSDoc; readonly fullName?: JSDocNamespaceDeclaration | Identifier; @@ -3834,7 +4069,7 @@ export interface JSDocThrowsTag extends JSDocTag { readonly typeExpression?: JSDocTypeExpression; } -export interface JSDocSignature extends JSDocType, Declaration { +export interface JSDocSignature extends JSDocType, Declaration, JSDocContainer, LocalsContainer { readonly kind: SyntaxKind.JSDocSignature; readonly typeParameters?: readonly JSDocTemplateTag[]; readonly parameters: readonly JSDocParameterTag[]; @@ -3858,7 +4093,7 @@ export interface JSDocParameterTag extends JSDocPropertyLikeTag { readonly kind: SyntaxKind.JSDocParameterTag; } -export interface JSDocTypeLiteral extends JSDocType { +export interface JSDocTypeLiteral extends JSDocType, Declaration { readonly kind: SyntaxKind.JSDocTypeLiteral; readonly jsDocPropertyTags?: readonly JSDocPropertyLikeTag[]; /** If true, then this type literal represents an *array* of its type. */ @@ -3992,7 +4227,7 @@ export interface RedirectInfo { export type ResolutionMode = ModuleKind.ESNext | ModuleKind.CommonJS | undefined; // Source files are declarations when they are external modules. -export interface SourceFile extends Declaration { +export interface SourceFile extends Declaration, LocalsContainer { readonly kind: SyntaxKind.SourceFile; readonly statements: NodeArray; readonly endOfFileToken: Token; @@ -4094,7 +4329,7 @@ export interface SourceFile extends Declaration { // JS identifier-declarations that are intended to merge with globals /** @internal */ jsGlobalAugmentations?: SymbolTable; - /** @internal */ identifiers: Map; // Map from a string to an interned string + /** @internal */ identifiers: ReadonlyMap; // Map from a string to an interned string /** @internal */ nodeCount: number; /** @internal */ identifierCount: number; /** @internal */ symbolCount: number; @@ -4141,6 +4376,31 @@ export interface SourceFile extends Declaration { /** @internal */ endFlowNode?: FlowNode; } +/** @internal */ +export interface ReadonlyPragmaContext { + languageVersion: ScriptTarget; + pragmas?: ReadonlyPragmaMap; + checkJsDirective?: CheckJsDirective; + referencedFiles: readonly FileReference[]; + typeReferenceDirectives: readonly FileReference[]; + libReferenceDirectives: readonly FileReference[]; + amdDependencies: readonly AmdDependency[]; + hasNoDefaultLib?: boolean; + moduleName?: string; +} + +/** @internal */ +export interface PragmaContext extends ReadonlyPragmaContext { + pragmas?: PragmaMap; + referencedFiles: FileReference[]; + typeReferenceDirectives: FileReference[]; + libReferenceDirectives: FileReference[]; + amdDependencies: AmdDependency[]; +} + +/** @internal */ +export interface SourceFile extends ReadonlyPragmaContext {} + /** @internal */ export interface CommentDirective { range: TextRange; @@ -4947,7 +5207,7 @@ export interface TypeChecker { * * @internal */ - tryGetThisTypeAt(node: Node, includeGlobalThis?: boolean, container?: Node): Type | undefined; + tryGetThisTypeAt(node: Node, includeGlobalThis?: boolean, container?: ThisContainer): Type | undefined; /** @internal */ getTypeArgumentConstraint(node: TypeNode): Type | undefined; /** @@ -5124,7 +5384,7 @@ export interface SymbolWalker { // This was previously deprecated in our public API, but is still used internally /** @internal */ -export interface SymbolWriter extends SymbolTracker { +export interface SymbolWriter { writeKeyword(text: string): void; writeOperator(text: string): void; writePunctuation(text: string): void; @@ -5696,7 +5956,17 @@ export interface NodeLinks { isExhaustive?: boolean | 0; // Is node an exhaustive switch statement (0 indicates in-process resolution) skipDirectInference?: true; // Flag set by the API `getContextualType` call on a node when `Completions` is passed to force the checker to skip making inferences to a node's type declarationRequiresScopeChange?: boolean; // Set by `useOuterVariableScopeInParameter` in checker when downlevel emit would change the name resolution scope inside of a parameter. - serializedTypes?: Map; // Collection of types serialized at this location + serializedTypes?: Map; // Collection of types serialized at this location + + contextualType?: Type; // Used to temporarily assign a contextual type during overload resolution + inferenceContext?: InferenceContext; // Inference context for contextual type +} + +/** @internal */ +export interface SerializedTypeEntry { + node: TypeNode; + truncating?: boolean; + addedLength: number; } export const enum TypeFlags { @@ -7863,11 +8133,12 @@ export interface NodeFactory { createToken(token: SyntaxKind.NullKeyword): NullLiteral; createToken(token: SyntaxKind.TrueKeyword): TrueLiteral; createToken(token: SyntaxKind.FalseKeyword): FalseLiteral; + createToken(token: SyntaxKind.EndOfFileToken): EndOfFileToken; + createToken(token: SyntaxKind.Unknown): Token; createToken(token: TKind): PunctuationToken; createToken(token: TKind): KeywordTypeNode; createToken(token: TKind): ModifierToken; createToken(token: TKind): KeywordToken; - createToken(token: TKind): Token; /** @internal */ createToken(token: TKind): Token; // @@ -8336,6 +8607,8 @@ export interface NodeFactory { createSourceFile(statements: readonly Statement[], endOfFileToken: EndOfFileToken, flags: NodeFlags): SourceFile; updateSourceFile(node: SourceFile, statements: readonly Statement[], isDeclarationFile?: boolean, referencedFiles?: readonly FileReference[], typeReferences?: readonly FileReference[], hasNoDefaultLib?: boolean, libReferences?: readonly FileReference[]): SourceFile; + /** @internal */ createRedirectedSourceFile(redirectInfo: RedirectInfo): SourceFile; + /** @internal */ createUnparsedSource(prologues: readonly UnparsedPrologue[], syntheticReferences: readonly UnparsedSyntheticReference[] | undefined, texts: readonly UnparsedSourceText[]): UnparsedSource; /** @internal */ createUnparsedPrologue(data?: string): UnparsedPrologue; /** @internal */ createUnparsedPrepend(data: string | undefined, texts: readonly UnparsedSourceText[]): UnparsedPrepend; diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index 7ce2c8be94389..5c65c652db3ef 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -34,6 +34,7 @@ import { BundleFileTextLike, CallExpression, CallLikeExpression, + CallSignatureDeclaration, canHaveDecorators, canHaveIllegalDecorators, canHaveModifiers, @@ -66,6 +67,7 @@ import { concatenate, ConditionalExpression, ConstructorDeclaration, + ConstructSignatureDeclaration, contains, containsPath, createGetCanonicalFileName, @@ -190,6 +192,7 @@ import { getTrailingCommentRanges, HasExpressionInitializer, hasExtension, + HasFlowNode, HasInitializer, hasInitializer, HasJSDoc, @@ -214,6 +217,7 @@ import { ImportTypeNode, IndexInfo, indexOfAnyCharCode, + IndexSignatureDeclaration, InitializedVariableDeclaration, insertSorted, InterfaceDeclaration, @@ -357,6 +361,7 @@ import { MapLike, MemberName, MethodDeclaration, + MethodSignature, ModeAwareCache, ModifierFlags, ModifierLike, @@ -602,10 +607,6 @@ function createSingleLineStringWriter(): EmitTextWriter { increaseIndent: noop, decreaseIndent: noop, clear: () => str = "", - trackSymbol: () => false, - reportInaccessibleThisError: noop, - reportInaccessibleUniqueSymbolError: noop, - reportPrivateInBaseOfClassExpression: noop, }; } @@ -2274,7 +2275,7 @@ export function isObjectLiteralMethod(node: Node): node is MethodDeclaration { } /** @internal */ -export function isObjectLiteralOrClassExpressionMethodOrAccessor(node: Node): node is MethodDeclaration { +export function isObjectLiteralOrClassExpressionMethodOrAccessor(node: Node): node is MethodDeclaration | AccessorDeclaration { return (node.kind === SyntaxKind.MethodDeclaration || node.kind === SyntaxKind.GetAccessor || node.kind === SyntaxKind.SetAccessor) && (node.parent.kind === SyntaxKind.ObjectLiteralExpression || node.parent.kind === SyntaxKind.ClassExpression); @@ -2362,7 +2363,34 @@ export function getContainingFunctionOrClassStaticBlock(node: Node): SignatureDe } /** @internal */ -export function getThisContainer(node: Node, includeArrowFunctions: boolean): Node { +export type ThisContainer = + | FunctionDeclaration + | FunctionExpression + | ModuleDeclaration + | ClassStaticBlockDeclaration + | PropertyDeclaration + | PropertySignature + | MethodDeclaration + | MethodSignature + | ConstructorDeclaration + | GetAccessorDeclaration + | SetAccessorDeclaration + | CallSignatureDeclaration + | ConstructSignatureDeclaration + | IndexSignatureDeclaration + | EnumDeclaration + | SourceFile + ; + +/** @internal */ +export function getThisContainer(node: Node, includeArrowFunctions: false, includeClassComputedPropertyName: false): ThisContainer; +/** @internal */ +export function getThisContainer(node: Node, includeArrowFunctions: false, includeClassComputedPropertyName: boolean): ThisContainer | ComputedPropertyName; +/** @internal */ +export function getThisContainer(node: Node, includeArrowFunctions: boolean, includeClassComputedPropertyName: false): ThisContainer | ArrowFunction; +/** @internal */ +export function getThisContainer(node: Node, includeArrowFunctions: boolean, includeClassComputedPropertyName: boolean): ThisContainer | ArrowFunction | ComputedPropertyName; +export function getThisContainer(node: Node, includeArrowFunctions: boolean, includeClassComputedPropertyName: boolean) { Debug.assert(node.kind !== SyntaxKind.SourceFile); while (true) { node = node.parent; @@ -2375,15 +2403,15 @@ export function getThisContainer(node: Node, includeArrowFunctions: boolean): No // then the computed property is not a 'this' container. // A computed property name in a class needs to be a this container // so that we can error on it. - if (isClassLike(node.parent.parent)) { - return node; + if (includeClassComputedPropertyName && isClassLike(node.parent.parent)) { + return node as ComputedPropertyName; } // If this is a computed property, then the parent should not // make it a this container. The parent might be a property // in an object literal, like a method or accessor. But in order for // such a parent to be a this container, the reference must be in // the *body* of the container. - node = node.parent; + node = node.parent.parent; break; case SyntaxKind.Decorator: // Decorators are always applied outside of the body of a class or method. @@ -2420,7 +2448,7 @@ export function getThisContainer(node: Node, includeArrowFunctions: boolean): No case SyntaxKind.IndexSignature: case SyntaxKind.EnumDeclaration: case SyntaxKind.SourceFile: - return node; + return node as ThisContainer | ArrowFunction; } } } @@ -2461,13 +2489,13 @@ export function isInTopLevelContext(node: Node) { if (isIdentifier(node) && (isClassDeclaration(node.parent) || isFunctionDeclaration(node.parent)) && node.parent.name === node) { node = node.parent; } - const container = getThisContainer(node, /*includeArrowFunctions*/ true); + const container = getThisContainer(node, /*includeArrowFunctions*/ true, /*includeClassComputedPropertyName*/ false); return isSourceFile(container); } /** @internal */ export function getNewTargetContainer(node: Node) { - const container = getThisContainer(node, /*includeArrowFunctions*/ false); + const container = getThisContainer(node, /*includeArrowFunctions*/ false, /*includeClassComputedPropertyName*/ false); if (container) { switch (container.kind) { case SyntaxKind.Constructor: @@ -2480,6 +2508,26 @@ export function getNewTargetContainer(node: Node) { return undefined; } +/** @internal */ +export type SuperContainer = + | PropertyDeclaration + | PropertySignature + | MethodDeclaration + | MethodSignature + | ConstructorDeclaration + | GetAccessorDeclaration + | SetAccessorDeclaration + | ClassStaticBlockDeclaration + ; + +/** @internal */ +export type SuperContainerOrFunctions = + | SuperContainer + | FunctionDeclaration + | FunctionExpression + | ArrowFunction + ; + /** * Given an super call/property node, returns the closest node where * - a super call/property access is legal in the node and not legal in the parent node the node. @@ -2490,11 +2538,14 @@ export function getNewTargetContainer(node: Node) { * * @internal */ -export function getSuperContainer(node: Node, stopOnFunctions: boolean): Node { +export function getSuperContainer(node: Node, stopOnFunctions: false): SuperContainer | undefined; +/** @internal */ +export function getSuperContainer(node: Node, stopOnFunctions: boolean): SuperContainerOrFunctions | undefined; +export function getSuperContainer(node: Node, stopOnFunctions: boolean) { while (true) { node = node.parent; if (!node) { - return node; + return undefined; } switch (node.kind) { case SyntaxKind.ComputedPropertyName: @@ -2516,7 +2567,7 @@ export function getSuperContainer(node: Node, stopOnFunctions: boolean): Node { case SyntaxKind.GetAccessor: case SyntaxKind.SetAccessor: case SyntaxKind.ClassStaticBlockDeclaration: - return node; + return node as SuperContainerOrFunctions; case SyntaxKind.Decorator: // Decorators are always applied outside of the body of a class or method. if (node.parent.kind === SyntaxKind.Parameter && isClassElement(node.parent.parent)) { @@ -3355,7 +3406,13 @@ export function getInitializerOfBinaryExpression(expr: BinaryExpression) { } /** @internal */ -export function isPrototypePropertyAssignment(node: Node): node is BinaryExpression { +export interface PrototypePropertyAssignment extends AssignmentExpression { + _prototypePropertyAssignmentBrand: any; + readonly left: AccessExpression; +} + +/** @internal */ +export function isPrototypePropertyAssignment(node: Node): node is PrototypePropertyAssignment { return isBinaryExpression(node) && getAssignmentDeclarationKind(node) === AssignmentDeclarationKind.PrototypeProperty; } @@ -3556,6 +3613,106 @@ function getNestedModuleDeclaration(node: Node): Node | undefined { : undefined; } +/** @internal */ +export function canHaveFlowNode(node: Node): node is HasFlowNode { + if (node.kind >= SyntaxKind.FirstStatement && node.kind <= SyntaxKind.LastStatement) { + return true; + } + + switch (node.kind) { + case SyntaxKind.Identifier: + case SyntaxKind.ThisKeyword: + case SyntaxKind.SuperKeyword: + case SyntaxKind.QualifiedName: + case SyntaxKind.MetaProperty: + case SyntaxKind.ElementAccessExpression: + case SyntaxKind.PropertyAccessExpression: + case SyntaxKind.BindingElement: + case SyntaxKind.FunctionExpression: + case SyntaxKind.ArrowFunction: + case SyntaxKind.MethodDeclaration: + case SyntaxKind.GetAccessor: + case SyntaxKind.SetAccessor: + return true; + default: + return false; + } +} + +/** @internal */ +export function canHaveJSDoc(node: Node): node is HasJSDoc { + switch (node.kind) { + case SyntaxKind.ArrowFunction: + case SyntaxKind.BinaryExpression: + case SyntaxKind.Block: + case SyntaxKind.BreakStatement: + case SyntaxKind.CallSignature: + case SyntaxKind.CaseClause: + case SyntaxKind.ClassDeclaration: + case SyntaxKind.ClassExpression: + case SyntaxKind.ClassStaticBlockDeclaration: + case SyntaxKind.Constructor: + case SyntaxKind.ConstructorType: + case SyntaxKind.ConstructSignature: + case SyntaxKind.ContinueStatement: + case SyntaxKind.DebuggerStatement: + case SyntaxKind.DoStatement: + case SyntaxKind.ElementAccessExpression: + case SyntaxKind.EmptyStatement: + case SyntaxKind.EndOfFileToken: + case SyntaxKind.EnumDeclaration: + case SyntaxKind.EnumMember: + case SyntaxKind.ExportAssignment: + case SyntaxKind.ExportDeclaration: + case SyntaxKind.ExportSpecifier: + case SyntaxKind.ExpressionStatement: + case SyntaxKind.ForInStatement: + case SyntaxKind.ForOfStatement: + case SyntaxKind.ForStatement: + case SyntaxKind.FunctionDeclaration: + case SyntaxKind.FunctionExpression: + case SyntaxKind.FunctionType: + case SyntaxKind.GetAccessor: + case SyntaxKind.Identifier: + case SyntaxKind.IfStatement: + case SyntaxKind.ImportDeclaration: + case SyntaxKind.ImportEqualsDeclaration: + case SyntaxKind.IndexSignature: + case SyntaxKind.InterfaceDeclaration: + case SyntaxKind.JSDocFunctionType: + case SyntaxKind.JSDocSignature: + case SyntaxKind.LabeledStatement: + case SyntaxKind.MethodDeclaration: + case SyntaxKind.MethodSignature: + case SyntaxKind.ModuleDeclaration: + case SyntaxKind.NamedTupleMember: + case SyntaxKind.NamespaceExportDeclaration: + case SyntaxKind.ObjectLiteralExpression: + case SyntaxKind.Parameter: + case SyntaxKind.ParenthesizedExpression: + case SyntaxKind.PropertyAccessExpression: + case SyntaxKind.PropertyAssignment: + case SyntaxKind.PropertyDeclaration: + case SyntaxKind.PropertySignature: + case SyntaxKind.ReturnStatement: + case SyntaxKind.SetAccessor: + case SyntaxKind.ShorthandPropertyAssignment: + case SyntaxKind.SpreadAssignment: + case SyntaxKind.SwitchStatement: + case SyntaxKind.ThrowStatement: + case SyntaxKind.TryStatement: + case SyntaxKind.TypeAliasDeclaration: + case SyntaxKind.TypeParameter: + case SyntaxKind.VariableDeclaration: + case SyntaxKind.VariableStatement: + case SyntaxKind.WhileStatement: + case SyntaxKind.WithStatement: + return true; + default: + return false; + } +} + /** @internal */ export function getJSDocCommentsAndTags(hostNode: Node, noCache?: boolean): readonly (JSDoc | JSDocTag)[] { let result: (JSDoc | JSDocTag)[] | undefined; @@ -3944,7 +4101,7 @@ export function getDeclarationFromName(name: Node): Declaration | undefined { const binExp = parent.parent; return isBinaryExpression(binExp) && getAssignmentDeclarationKind(binExp) !== AssignmentDeclarationKind.None && - (binExp.left.symbol || binExp.symbol) && + ((binExp.left as BindableStaticNameExpression).symbol || binExp.symbol) && getNameOfDeclaration(binExp) === name ? binExp : undefined; @@ -5164,10 +5321,6 @@ export function createTextWriter(newLine: string): EmitTextWriter { hasTrailingComment: () => hasTrailingComment, hasTrailingWhitespace: () => !!output.length && isWhiteSpaceLike(output.charCodeAt(output.length - 1)), clear: reset, - reportInaccessibleThisError: noop, - reportPrivateInBaseOfClassExpression: noop, - reportInaccessibleUniqueSymbolError: noop, - trackSymbol: () => false, writeKeyword: write, writeOperator: write, writeParameter: write, @@ -7138,6 +7291,7 @@ function Node(this: Mutable, kind: SyntaxKind, pos: number, end: number) { this.transformFlags = TransformFlags.None; this.parent = undefined!; this.original = undefined; + this.emitNode = undefined; } function Token(this: Mutable, kind: SyntaxKind, pos: number, end: number) { @@ -7148,6 +7302,7 @@ function Token(this: Mutable, kind: SyntaxKind, pos: number, end: number) this.flags = NodeFlags.None; this.transformFlags = TransformFlags.None; this.parent = undefined!; + this.emitNode = undefined; } function Identifier(this: Mutable, kind: SyntaxKind, pos: number, end: number) { @@ -7159,7 +7314,8 @@ function Identifier(this: Mutable, kind: SyntaxKind, pos: number, end: num this.transformFlags = TransformFlags.None; this.parent = undefined!; this.original = undefined; - this.flowNode = undefined; + this.emitNode = undefined; + (this as Identifier).flowNode = undefined; } function SourceMapSource(this: SourceMapSource, fileName: string, text: string, skipTrivia?: (pos: number) => number) { diff --git a/src/compiler/utilitiesPublic.ts b/src/compiler/utilitiesPublic.ts index e6c0c5a05602a..a70f299d61b6e 100644 --- a/src/compiler/utilitiesPublic.ts +++ b/src/compiler/utilitiesPublic.ts @@ -24,6 +24,7 @@ import { CallExpression, CallLikeExpression, canHaveIllegalTypeParameters, + canHaveJSDoc, CaseOrDefaultClause, CharacterCodes, ClassElement, @@ -82,6 +83,7 @@ import { HasExpressionInitializer, HasInitializer, HasJSDoc, + HasLocals, HasModifiers, hasProperty, hasSyntacticModifier, @@ -1142,14 +1144,15 @@ export function getJSDocReturnType(node: Node): TypeNode | undefined { } function getJSDocTagsWorker(node: Node, noCache?: boolean): readonly JSDocTag[] { - let tags = (node as JSDocContainer).jsDocCache; + if (!canHaveJSDoc(node)) return emptyArray; + let tags = node.jsDocCache; // If cache is 'null', that means we did the work of searching for JSDoc tags and came up with nothing. if (tags === undefined || noCache) { const comments = getJSDocCommentsAndTags(node, noCache); Debug.assert(comments.length < 2 || comments[0] !== comments[1]); tags = flatMap(comments, j => isJSDoc(j) ? j.tags : j); if (!noCache) { - (node as JSDocContainer).jsDocCache = tags; + node.jsDocCache = tags; } } return tags; @@ -2058,6 +2061,120 @@ export function isModuleOrEnumDeclaration(node: Node): node is ModuleDeclaration return node.kind === SyntaxKind.ModuleDeclaration || node.kind === SyntaxKind.EnumDeclaration; } +/** @internal */ +export function canHaveSymbol(node: Node): node is Declaration { + // NOTE: This should cover all possible declarations except MissingDeclaration and SemicolonClassElement + // since they aren't actually declarations and can't have a symbol. + switch (node.kind) { + case SyntaxKind.ArrowFunction: + case SyntaxKind.BinaryExpression: + case SyntaxKind.BindingElement: + case SyntaxKind.CallExpression: + case SyntaxKind.CallSignature: + case SyntaxKind.ClassDeclaration: + case SyntaxKind.ClassExpression: + case SyntaxKind.ClassStaticBlockDeclaration: + case SyntaxKind.Constructor: + case SyntaxKind.ConstructorType: + case SyntaxKind.ConstructSignature: + case SyntaxKind.ElementAccessExpression: + case SyntaxKind.EnumDeclaration: + case SyntaxKind.EnumMember: + case SyntaxKind.ExportAssignment: + case SyntaxKind.ExportDeclaration: + case SyntaxKind.ExportSpecifier: + case SyntaxKind.FunctionDeclaration: + case SyntaxKind.FunctionExpression: + case SyntaxKind.FunctionType: + case SyntaxKind.GetAccessor: + case SyntaxKind.Identifier: + case SyntaxKind.ImportClause: + case SyntaxKind.ImportEqualsDeclaration: + case SyntaxKind.ImportSpecifier: + case SyntaxKind.IndexSignature: + case SyntaxKind.InterfaceDeclaration: + case SyntaxKind.JSDocCallbackTag: + case SyntaxKind.JSDocEnumTag: + case SyntaxKind.JSDocFunctionType: + case SyntaxKind.JSDocParameterTag: + case SyntaxKind.JSDocPropertyTag: + case SyntaxKind.JSDocSignature: + case SyntaxKind.JSDocTypedefTag: + case SyntaxKind.JSDocTypeLiteral: + case SyntaxKind.JsxAttribute: + case SyntaxKind.JsxAttributes: + case SyntaxKind.JsxSpreadAttribute: + case SyntaxKind.MappedType: + case SyntaxKind.MethodDeclaration: + case SyntaxKind.MethodSignature: + case SyntaxKind.ModuleDeclaration: + case SyntaxKind.NamedTupleMember: + case SyntaxKind.NamespaceExport: + case SyntaxKind.NamespaceExportDeclaration: + case SyntaxKind.NamespaceImport: + case SyntaxKind.NewExpression: + case SyntaxKind.NoSubstitutionTemplateLiteral: + case SyntaxKind.NumericLiteral: + case SyntaxKind.ObjectLiteralExpression: + case SyntaxKind.Parameter: + case SyntaxKind.PropertyAccessExpression: + case SyntaxKind.PropertyAssignment: + case SyntaxKind.PropertyDeclaration: + case SyntaxKind.PropertySignature: + case SyntaxKind.SetAccessor: + case SyntaxKind.ShorthandPropertyAssignment: + case SyntaxKind.SourceFile: + case SyntaxKind.SpreadAssignment: + case SyntaxKind.StringLiteral: + case SyntaxKind.TypeAliasDeclaration: + case SyntaxKind.TypeLiteral: + case SyntaxKind.TypeParameter: + case SyntaxKind.VariableDeclaration: + return true; + default: + return false; + } +} + +/** @internal */ +export function canHaveLocals(node: Node): node is HasLocals { + switch (node.kind) { + case SyntaxKind.ArrowFunction: + case SyntaxKind.Block: + case SyntaxKind.CallSignature: + case SyntaxKind.CaseBlock: + case SyntaxKind.CatchClause: + case SyntaxKind.ClassStaticBlockDeclaration: + case SyntaxKind.ConditionalType: + case SyntaxKind.Constructor: + case SyntaxKind.ConstructorType: + case SyntaxKind.ConstructSignature: + case SyntaxKind.ForStatement: + case SyntaxKind.ForInStatement: + case SyntaxKind.ForOfStatement: + case SyntaxKind.FunctionDeclaration: + case SyntaxKind.FunctionExpression: + case SyntaxKind.FunctionType: + case SyntaxKind.GetAccessor: + case SyntaxKind.IndexSignature: + case SyntaxKind.JSDocCallbackTag: + case SyntaxKind.JSDocEnumTag: + case SyntaxKind.JSDocFunctionType: + case SyntaxKind.JSDocSignature: + case SyntaxKind.JSDocTypedefTag: + case SyntaxKind.MappedType: + case SyntaxKind.MethodDeclaration: + case SyntaxKind.MethodSignature: + case SyntaxKind.ModuleDeclaration: + case SyntaxKind.SetAccessor: + case SyntaxKind.SourceFile: + case SyntaxKind.TypeAliasDeclaration: + return true; + default: + return false; + } +} + function isDeclarationKind(kind: SyntaxKind) { return kind === SyntaxKind.ArrowFunction || kind === SyntaxKind.BindingElement @@ -2289,6 +2406,8 @@ export function isGetAccessor(node: Node): node is GetAccessorDeclaration { */ // TODO: GH#19856 Would like to return `node is Node & { jsDoc: JSDoc[] }` but it causes long compile times export function hasJSDocNodes(node: Node): node is HasJSDoc { + if (!canHaveJSDoc(node)) return false; + const { jsDoc } = node as JSDocContainer; return !!jsDoc && jsDoc.length > 0; } diff --git a/src/harness/harnessUtils.ts b/src/harness/harnessUtils.ts index dcf9a3a407f4f..0946eaa802c83 100644 --- a/src/harness/harnessUtils.ts +++ b/src/harness/harnessUtils.ts @@ -126,6 +126,7 @@ export function assertInvariants(node: ts.Node | undefined, parent: ts.Node | un childName === "nextContainer" || childName === "modifiers" || childName === "externalModuleIndicator" || + childName === "original" || // for now ignore jsdoc comments childName === "jsDocComment" || childName === "checkJsDirective" || @@ -200,9 +201,16 @@ export function sourceFileToJSON(file: ts.Node): string { case "symbolCount": case "identifierCount": case "scriptSnapshot": + case "autoGenerateFlags": // Blocklist of items we never put in the baseline file. break; + case "hasExtendedUnicodeEscape": + if ((n as any).hasExtendedUnicodeEscape) { + o.hasExtendedUnicodeEscape = true; + } + break; + case "originalKeywordKind": o[propertyName] = getKindName((n as any)[propertyName]); break; @@ -222,8 +230,8 @@ export function sourceFileToJSON(file: ts.Node): string { break; case "nextContainer": - if (n.nextContainer) { - o[propertyName] = { kind: n.nextContainer.kind, pos: n.nextContainer.pos, end: n.nextContainer.end }; + if ((n as ts.HasLocals).nextContainer) { + o[propertyName] = { kind: (n as ts.HasLocals).nextContainer!.kind, pos: (n as ts.HasLocals).nextContainer!.pos, end: (n as ts.HasLocals).nextContainer!.end }; } break; diff --git a/src/services/codefixes/convertToAsyncFunction.ts b/src/services/codefixes/convertToAsyncFunction.ts index 999dab6f413e5..e6851157938fe 100644 --- a/src/services/codefixes/convertToAsyncFunction.ts +++ b/src/services/codefixes/convertToAsyncFunction.ts @@ -6,6 +6,7 @@ import { Block, CallExpression, canBeConvertedToAsync, + canHaveSymbol, CodeFixContext, concatenate, createMultiMap, @@ -867,7 +868,7 @@ function getArgBindingName(funcNode: Expression, transformer: Transformer): Synt } function getSymbol(node: Node): Symbol | undefined { - return node.symbol ? node.symbol : transformer.checker.getSymbolAtLocation(node); + return tryCast(node, canHaveSymbol)?.symbol ?? transformer.checker.getSymbolAtLocation(node); } function getOriginalNode(node: Node): Node { diff --git a/src/services/codefixes/fixImplicitThis.ts b/src/services/codefixes/fixImplicitThis.ts index cd288e531df8c..c8f02aba81850 100644 --- a/src/services/codefixes/fixImplicitThis.ts +++ b/src/services/codefixes/fixImplicitThis.ts @@ -46,10 +46,10 @@ function doChange(changes: textChanges.ChangeTracker, sourceFile: SourceFile, po const token = getTokenAtPosition(sourceFile, pos); if (!isThis(token)) return undefined; - const fn = getThisContainer(token, /*includeArrowFunctions*/ false); + const fn = getThisContainer(token, /*includeArrowFunctions*/ false, /*includeClassComputedPropertyName*/ false); if (!isFunctionDeclaration(fn) && !isFunctionExpression(fn)) return undefined; - if (!isSourceFile(getThisContainer(fn, /*includeArrowFunctions*/ false))) { // 'this' is defined outside, convert to arrow function + if (!isSourceFile(getThisContainer(fn, /*includeArrowFunctions*/ false, /*includeClassComputedPropertyName*/ false))) { // 'this' is defined outside, convert to arrow function const fnKeyword = Debug.checkDefined(findChildOfKind(fn, SyntaxKind.FunctionKeyword, sourceFile)); const { name } = fn; const body = Debug.checkDefined(fn.body); // Should be defined because the function contained a 'this' expression diff --git a/src/services/codefixes/fixImportNonExportedMember.ts b/src/services/codefixes/fixImportNonExportedMember.ts index ba1ec81fc945f..23731400a1601 100644 --- a/src/services/codefixes/fixImportNonExportedMember.ts +++ b/src/services/codefixes/fixImportNonExportedMember.ts @@ -1,5 +1,6 @@ import { canHaveExportModifier, + canHaveLocals, Declaration, Diagnostics, ExportDeclaration, @@ -125,7 +126,7 @@ function getInfo(sourceFile: SourceFile, pos: number, program: Program): Info | if (moduleSourceFile === undefined || isSourceFileFromLibrary(program, moduleSourceFile)) return undefined; const moduleSymbol = moduleSourceFile.symbol; - const locals = moduleSymbol.valueDeclaration?.locals; + const locals = tryCast(moduleSymbol.valueDeclaration, canHaveLocals)?.locals; if (locals === undefined) return undefined; const localSymbol = locals.get(token.escapedText); diff --git a/src/services/completions.ts b/src/services/completions.ts index c9de7d2d194a2..6e02fd1e567a4 100644 --- a/src/services/completions.ts +++ b/src/services/completions.ts @@ -294,6 +294,7 @@ import { PropertyAccessExpression, PropertyDeclaration, PropertyName, + PropertySignature, PseudoBigInt, pseudoBigIntToString, QualifiedName, @@ -334,6 +335,7 @@ import { textPart, TextRange, TextSpan, + ThisContainer, timestamp, Token, TokenSyntaxKind, @@ -3308,7 +3310,7 @@ function getCompletionData( // Need to insert 'this.' before properties of `this` type, so only do that if `includeInsertTextCompletions` if (preferences.includeCompletionsWithInsertText && scopeNode.kind !== SyntaxKind.SourceFile) { - const thisType = typeChecker.tryGetThisTypeAt(scopeNode, /*includeGlobalThis*/ false, isClassLike(scopeNode.parent) ? scopeNode : undefined); + const thisType = typeChecker.tryGetThisTypeAt(scopeNode, /*includeGlobalThis*/ false, isClassLike(scopeNode.parent) ? scopeNode as ThisContainer : undefined); if (thisType && !isProbablyGlobalType(thisType, sourceFile, typeChecker)) { for (const symbol of getPropertiesForCompletion(thisType, typeChecker)) { symbolToOriginInfoMap[symbols.length] = { kind: SymbolOriginInfoKind.ThisType }; @@ -4877,7 +4879,7 @@ function getConstraintOfTypeArgumentProperty(node: Node, checker: TypeChecker): switch (node.kind) { case SyntaxKind.PropertySignature: - return checker.getTypeOfPropertyOfContextualType(t, node.symbol.escapedName); + return checker.getTypeOfPropertyOfContextualType(t, (node as PropertySignature).symbol.escapedName); case SyntaxKind.IntersectionType: case SyntaxKind.TypeLiteral: case SyntaxKind.UnionType: diff --git a/src/services/documentHighlights.ts b/src/services/documentHighlights.ts index c3bb005234dca..797d7346b36c7 100644 --- a/src/services/documentHighlights.ts +++ b/src/services/documentHighlights.ts @@ -5,6 +5,7 @@ import { Block, BreakOrContinueStatement, CancellationToken, + canHaveSymbol, CaseClause, cast, concatenate, @@ -78,6 +79,7 @@ import { ThrowStatement, toArray, toPath, + tryCast, TryStatement, } from "./_namespaces/ts"; @@ -184,7 +186,7 @@ export namespace DocumentHighlights { } function getFromAllDeclarations(nodeTest: (node: Node) => node is T, keywords: readonly SyntaxKind[]): HighlightSpan[] | undefined { - return useParent(node.parent, nodeTest, decl => mapDefined(decl.symbol.declarations, d => + return useParent(node.parent, nodeTest, decl => mapDefined(tryCast(decl, canHaveSymbol)?.symbol.declarations, d => nodeTest(d) ? find(d.getChildren(sourceFile), c => contains(keywords, c.kind)) : undefined)); } diff --git a/src/services/findAllReferences.ts b/src/services/findAllReferences.ts index dad6d6f2dfaaf..01ad83b784169 100644 --- a/src/services/findAllReferences.ts +++ b/src/services/findAllReferences.ts @@ -8,6 +8,7 @@ import { Block, CallExpression, CancellationToken, + canHaveSymbol, cast, CheckFlags, ClassLikeDeclaration, @@ -190,6 +191,7 @@ import { NodeFlags, nodeSeenTracker, NumericLiteral, + ObjectLiteralExpression, ParameterDeclaration, ParenthesizedExpression, Path, @@ -218,6 +220,7 @@ import { StringLiteral, StringLiteralLike, stripQuotes, + SuperContainer, Symbol, SymbolDisplay, SymbolDisplayPart, @@ -234,6 +237,7 @@ import { tryGetClassExtendingExpressionWithTypeArguments, tryGetImportFromModuleSpecifier, TypeChecker, + TypeLiteralNode, VariableDeclaration, } from "./_namespaces/ts"; import { @@ -1882,7 +1886,7 @@ export namespace Core { // Use the parent symbol if the location is commonjs require syntax on javascript files only. if (isInJSFile(referenceLocation) - && referenceLocation.parent.kind === SyntaxKind.BindingElement + && isBindingElement(referenceLocation.parent) && isVariableDeclarationInitializedToBareOrAccessedRequire(referenceLocation.parent.parent.parent)) { referenceSymbol = referenceLocation.parent.symbol; // The parent will not have a symbol if it's an ObjectBindingPattern (when destructuring is used). In @@ -2253,7 +2257,7 @@ export namespace Core { } function getReferencesForSuperKeyword(superKeyword: Node): SymbolAndEntries[] | undefined { - let searchSpaceNode = getSuperContainer(superKeyword, /*stopOnFunctions*/ false); + let searchSpaceNode: SuperContainer | ClassLikeDeclaration | TypeLiteralNode | InterfaceDeclaration | ObjectLiteralExpression | undefined = getSuperContainer(superKeyword, /*stopOnFunctions*/ false); if (!searchSpaceNode) { return undefined; } @@ -2286,7 +2290,7 @@ export namespace Core { // If we have a 'super' container, we must have an enclosing class. // Now make sure the owning class is the same as the search-space // and has the same static qualifier as the original 'super's owner. - return container && isStatic(container) === !!staticFlag && container.parent.symbol === searchSpaceNode.symbol ? nodeEntry(node) : undefined; + return container && isStatic(container) === !!staticFlag && container.parent.symbol === searchSpaceNode!.symbol ? nodeEntry(node) : undefined; }); return [{ definition: { type: DefinitionKind.Symbol, symbol: searchSpaceNode.symbol }, references }]; @@ -2297,7 +2301,7 @@ export namespace Core { } function getReferencesForThisKeyword(thisOrSuperKeyword: Node, sourceFiles: readonly SourceFile[], cancellationToken: CancellationToken): SymbolAndEntries[] | undefined { - let searchSpaceNode = getThisContainer(thisOrSuperKeyword, /* includeArrowFunctions */ false); + let searchSpaceNode: Node = getThisContainer(thisOrSuperKeyword, /* includeArrowFunctions */ false, /*includeClassComputedPropertyName*/ false); // Whether 'this' occurs in a static context within a class. let staticFlag = ModifierFlags.Static; @@ -2339,11 +2343,12 @@ export namespace Core { if (!isThis(node)) { return false; } - const container = getThisContainer(node, /* includeArrowFunctions */ false); + const container = getThisContainer(node, /* includeArrowFunctions */ false, /*includeClassComputedPropertyName*/ false); + if (!canHaveSymbol(container)) return false; switch (searchSpaceNode.kind) { case SyntaxKind.FunctionExpression: case SyntaxKind.FunctionDeclaration: - return searchSpaceNode.symbol === container.symbol; + return (searchSpaceNode as FunctionExpression | FunctionDeclaration).symbol === container.symbol; case SyntaxKind.MethodDeclaration: case SyntaxKind.MethodSignature: return isObjectLiteralMethod(searchSpaceNode) && searchSpaceNode.symbol === container.symbol; @@ -2352,9 +2357,9 @@ export namespace Core { case SyntaxKind.ObjectLiteralExpression: // Make sure the container belongs to the same class/object literals // and has the appropriate static modifier from the original container. - return container.parent && searchSpaceNode.symbol === container.parent.symbol && isStatic(container) === !!staticFlag; + return container.parent && canHaveSymbol(container.parent) && (searchSpaceNode as ClassLikeDeclaration | ObjectLiteralExpression).symbol === container.parent.symbol && isStatic(container) === !!staticFlag; case SyntaxKind.SourceFile: - return container.kind === SyntaxKind.SourceFile && !isExternalModule(container as SourceFile) && !isParameterName(node); + return container.kind === SyntaxKind.SourceFile && !isExternalModule(container) && !isParameterName(node); } }); }).map(n => nodeEntry(n)); diff --git a/src/services/goToDefinition.ts b/src/services/goToDefinition.ts index e5fbe7f3bb10b..2529f9194610b 100644 --- a/src/services/goToDefinition.ts +++ b/src/services/goToDefinition.ts @@ -3,7 +3,7 @@ import { AssignmentExpression, AssignmentOperatorToken, CallLikeExpression, - concatenate, + canHaveSymbol, concatenate, createTextSpan, createTextSpanFromBounds, createTextSpanFromNode, @@ -245,7 +245,7 @@ function symbolMatchesSignature(s: Symbol, calledDeclaration: SignatureDeclarati return s === calledDeclaration.symbol || s === calledDeclaration.symbol.parent || isAssignmentExpression(calledDeclaration.parent) - || (!isCallLikeExpression(calledDeclaration.parent) && s === calledDeclaration.parent.symbol); + || (!isCallLikeExpression(calledDeclaration.parent) && s === tryCast(calledDeclaration.parent, canHaveSymbol)?.symbol); } // If the current location we want to find its definition is in an object literal, try to get the contextual type for the diff --git a/src/services/importTracker.ts b/src/services/importTracker.ts index 9b59debc1041f..1d59846a2a8f5 100644 --- a/src/services/importTracker.ts +++ b/src/services/importTracker.ts @@ -7,6 +7,7 @@ import { CallExpression, CancellationToken, canHaveModifiers, + canHaveSymbol, cast, Debug, ExportAssignment, @@ -73,6 +74,7 @@ import { SymbolFlags, symbolName, SyntaxKind, + tryCast, TypeChecker, ValidImportTypeNode, VariableDeclaration, @@ -683,10 +685,10 @@ function getExportEqualsLocalSymbol(importedSymbol: Symbol, checker: TypeChecker const decl = Debug.checkDefined(importedSymbol.valueDeclaration); if (isExportAssignment(decl)) { // `export = class {}` - return decl.expression.symbol; + return tryCast(decl.expression, canHaveSymbol)?.symbol; } else if (isBinaryExpression(decl)) { // `module.exports = class {}` - return decl.right.symbol; + return tryCast(decl.right, canHaveSymbol)?.symbol; } else if (isSourceFile(decl)) { // json module return decl.symbol; diff --git a/src/services/inlayHints.ts b/src/services/inlayHints.ts index 45bb04e6e1329..5544aaa920c02 100644 --- a/src/services/inlayHints.ts +++ b/src/services/inlayHints.ts @@ -387,7 +387,7 @@ export function provideInlayHints(context: InlayHintsContext): InlayHint[] { const printer = createPrinter(options); return usingSingleLineStringWriter(writer => { - const typeNode = checker.typeToTypeNode(type, /*enclosingDeclaration*/ undefined, flags, writer); + const typeNode = checker.typeToTypeNode(type, /*enclosingDeclaration*/ undefined, flags); Debug.assertIsDefined(typeNode, "should always get typenode"); printer.writeNode(EmitHint.Unspecified, typeNode, /*sourceFile*/ file, writer); }); diff --git a/src/services/refactors/convertExport.ts b/src/services/refactors/convertExport.ts index 689460c9ee2dd..64c758895e9d7 100644 --- a/src/services/refactors/convertExport.ts +++ b/src/services/refactors/convertExport.ts @@ -33,6 +33,7 @@ import { isStringLiteral, makeImport, ModifierFlags, + ModuleBlock, NamespaceDeclaration, Node, NodeFlags, @@ -122,7 +123,7 @@ function getInfo(context: RefactorContext, considerPartialSpans = true): ExportI } const checker = program.getTypeChecker(); - const exportingModuleSymbol = getExportingModuleSymbol(exportNode, checker); + const exportingModuleSymbol = getExportingModuleSymbol(exportNode.parent, checker); const flags = getSyntacticModifierFlags(exportNode) || ((isExportAssignment(exportNode) && !exportNode.isExportEquals) ? ModifierFlags.ExportDefault : ModifierFlags.None); const wasDefault = !!(flags & ModifierFlags.Default); @@ -319,8 +320,7 @@ function makeExportSpecifier(propertyName: string, name: string): ExportSpecifie return factory.createExportSpecifier(/*isTypeOnly*/ false, propertyName === name ? undefined : factory.createIdentifier(propertyName), factory.createIdentifier(name)); } -function getExportingModuleSymbol(node: Node, checker: TypeChecker) { - const parent = node.parent; +function getExportingModuleSymbol(parent: SourceFile | ModuleBlock, checker: TypeChecker) { if (isSourceFile(parent)) { return parent.symbol; } diff --git a/src/services/refactors/extractSymbol.ts b/src/services/refactors/extractSymbol.ts index 276804acf15a2..45aa5d1b90970 100644 --- a/src/services/refactors/extractSymbol.ts +++ b/src/services/refactors/extractSymbol.ts @@ -633,7 +633,7 @@ export function getRangeToExtract(sourceFile: SourceFile, span: TextSpan, invoke visit(nodeToCheck); if (rangeFacts & RangeFacts.UsesThis) { - const container = getThisContainer(nodeToCheck, /** includeArrowFunctions */ false); + const container = getThisContainer(nodeToCheck, /** includeArrowFunctions */ false, /*includeClassComputedPropertyName*/ false); if ( container.kind === SyntaxKind.FunctionDeclaration || (container.kind === SyntaxKind.MethodDeclaration && container.parent.kind === SyntaxKind.ObjectLiteralExpression) || diff --git a/src/services/refactors/moveToNewFile.ts b/src/services/refactors/moveToNewFile.ts index e2fce0deffa19..7950f25f5a6cf 100644 --- a/src/services/refactors/moveToNewFile.ts +++ b/src/services/refactors/moveToNewFile.ts @@ -10,7 +10,7 @@ import { CallExpression, canHaveDecorators, canHaveModifiers, - cast, + canHaveSymbol, cast, ClassDeclaration, codefix, combinePaths, @@ -505,7 +505,7 @@ function addExports(sourceFile: SourceFile, toMove: readonly Statement[], needEx return flatMap(toMove, statement => { if (isTopLevelDeclarationStatement(statement) && !isExported(sourceFile, statement, useEs6Exports) && - forEachTopLevelDeclaration(statement, d => needExport.has(Debug.checkDefined(d.symbol)))) { + forEachTopLevelDeclaration(statement, d => needExport.has(Debug.checkDefined(tryCast(d, canHaveSymbol)?.symbol)))) { const exports = addExport(statement, useEs6Exports); if (exports) return exports; } diff --git a/src/services/services.ts b/src/services/services.ts index b3daa66a40800..d227f3dee213f 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -594,7 +594,7 @@ class TokenOrIdentifierObject implements Node { } public getChildren(): Node[] { - return this.kind === SyntaxKind.EndOfFileToken ? (this as EndOfFileToken).jsDoc || emptyArray : emptyArray; + return this.kind === SyntaxKind.EndOfFileToken ? (this as Node as EndOfFileToken).jsDoc || emptyArray : emptyArray; } public getFirstToken(): Node | undefined { @@ -733,13 +733,15 @@ class IdentifierObject extends TokenOrIdentifierObject implements Identifier { public kind: SyntaxKind.Identifier = SyntaxKind.Identifier; public escapedText!: __String; public autoGenerateFlags!: GeneratedIdentifierFlags; - _primaryExpressionBrand: any; - _memberExpressionBrand: any; - _leftHandSideExpressionBrand: any; - _updateExpressionBrand: any; - _unaryExpressionBrand: any; - _expressionBrand: any; - _declarationBrand: any; + declare _primaryExpressionBrand: any; + declare _memberExpressionBrand: any; + declare _leftHandSideExpressionBrand: any; + declare _updateExpressionBrand: any; + declare _unaryExpressionBrand: any; + declare _expressionBrand: any; + declare _declarationBrand: any; + declare _jsdocContainerBrand: any; + declare _flowContainerBrand: any; /** @internal */typeArguments!: NodeArray; constructor(_kind: SyntaxKind.Identifier, pos: number, end: number) { super(pos, end); @@ -754,12 +756,12 @@ class PrivateIdentifierObject extends TokenOrIdentifierObject implements Private public kind: SyntaxKind.PrivateIdentifier = SyntaxKind.PrivateIdentifier; public escapedText!: __String; // public symbol!: Symbol; - _primaryExpressionBrand: any; - _memberExpressionBrand: any; - _leftHandSideExpressionBrand: any; - _updateExpressionBrand: any; - _unaryExpressionBrand: any; - _expressionBrand: any; + declare _primaryExpressionBrand: any; + declare _memberExpressionBrand: any; + declare _leftHandSideExpressionBrand: any; + declare _updateExpressionBrand: any; + declare _unaryExpressionBrand: any; + declare _expressionBrand: any; constructor(_kind: SyntaxKind.PrivateIdentifier, pos: number, end: number) { super(pos, end); } @@ -992,7 +994,8 @@ function findBaseOfDeclaration(checker: TypeChecker, declaration: Declaration class SourceFileObject extends NodeObject implements SourceFile { public kind: SyntaxKind.SourceFile = SyntaxKind.SourceFile; - public _declarationBrand: any; + declare _declarationBrand: any; + declare _localsContainerBrand: any; public fileName!: string; public path!: Path; public resolvedPath!: Path; diff --git a/src/services/signatureHelp.ts b/src/services/signatureHelp.ts index 1ca1b0ae6dd15..a50c64117daa9 100644 --- a/src/services/signatureHelp.ts +++ b/src/services/signatureHelp.ts @@ -3,6 +3,7 @@ import { BinaryExpression, CallLikeExpression, CancellationToken, + canHaveSymbol, CheckFlags, contains, countWhere, @@ -77,6 +78,7 @@ import { TemplateExpression, TextSpan, TransientSymbol, + tryCast, Type, TypeChecker, TypeParameter, @@ -431,7 +433,7 @@ function getContextualSignatureLocationInfo(startingToken: Node, sourceFile: Sou // The type of a function type node has a symbol at that node, but it's better to use the symbol for a parameter or type alias. function chooseBetterSymbol(s: Symbol): Symbol { return s.name === InternalSymbolName.Type - ? firstDefined(s.declarations, d => isFunctionTypeNode(d) ? d.parent.symbol : undefined) || s + ? firstDefined(s.declarations, d => isFunctionTypeNode(d) ? tryCast(d.parent, canHaveSymbol)?.symbol : undefined) || s : s; } diff --git a/src/services/suggestionDiagnostics.ts b/src/services/suggestionDiagnostics.ts index 3c242e580766c..87cf371041f37 100644 --- a/src/services/suggestionDiagnostics.ts +++ b/src/services/suggestionDiagnostics.ts @@ -34,6 +34,8 @@ import { isBlock, isCallExpression, isExportAssignment, + isFunctionDeclaration, + isFunctionExpression, isFunctionLike, isIdentifier, isPropertyAccessExpression, @@ -276,7 +278,7 @@ function getKeyFromNode(exp: FunctionLikeDeclaration) { } function canBeConvertedToClass(node: Node, checker: TypeChecker): boolean { - if (node.kind === SyntaxKind.FunctionExpression) { + if (isFunctionExpression(node)) { if (isVariableDeclaration(node.parent) && node.symbol.members?.size) { return true; } @@ -285,7 +287,7 @@ function canBeConvertedToClass(node: Node, checker: TypeChecker): boolean { return !!(symbol && (symbol.exports?.size || symbol.members?.size)); } - if (node.kind === SyntaxKind.FunctionDeclaration) { + if (isFunctionDeclaration(node)) { return !!node.symbol.members?.size; } diff --git a/src/services/symbolDisplay.ts b/src/services/symbolDisplay.ts index fff0b69e39eb0..3f31460b0a3e7 100644 --- a/src/services/symbolDisplay.ts +++ b/src/services/symbolDisplay.ts @@ -48,7 +48,6 @@ import { isFunctionBlock, isFunctionExpression, isFunctionLike, - isFunctionLikeKind, isIdentifier, isInExpressionContext, isJsxOpeningLikeElement, @@ -59,6 +58,7 @@ import { isObjectBindingPattern, isTaggedTemplateExpression, isThisInTypeQuery, + isTypeAliasDeclaration, isVarConst, JSDocTagInfo, JsxOpeningLikeElement, @@ -493,19 +493,19 @@ export function getSymbolDisplayPartsDocumentationAndSymbolKind(typeChecker: Typ const declaration = decl.parent; if (declaration) { - if (isFunctionLikeKind(declaration.kind)) { + if (isFunctionLike(declaration)) { addInPrefix(); - const signature = typeChecker.getSignatureFromDeclaration(declaration as SignatureDeclaration)!; // TODO: GH#18217 + const signature = typeChecker.getSignatureFromDeclaration(declaration)!; // TODO: GH#18217 if (declaration.kind === SyntaxKind.ConstructSignature) { displayParts.push(keywordPart(SyntaxKind.NewKeyword)); displayParts.push(spacePart()); } - else if (declaration.kind !== SyntaxKind.CallSignature && (declaration as SignatureDeclaration).name) { + else if (declaration.kind !== SyntaxKind.CallSignature && declaration.name) { addFullSymbolName(declaration.symbol); } addRange(displayParts, signatureToDisplayParts(typeChecker, signature, sourceFile, TypeFormatFlags.WriteTypeArgumentsOfSignature)); } - else if (declaration.kind === SyntaxKind.TypeAliasDeclaration) { + else if (isTypeAliasDeclaration(declaration)) { // Type alias type parameter // For example // type list = T[]; // Both T will go through same code path diff --git a/src/services/utilities.ts b/src/services/utilities.ts index 4fa12900724f2..ac93d22ba7699 100644 --- a/src/services/utilities.ts +++ b/src/services/utilities.ts @@ -271,7 +271,6 @@ import { nodeIsMissing, nodeIsPresent, nodeIsSynthesized, - noop, normalizePath, NoSubstitutionTemplateLiteral, notImplemented, @@ -2721,10 +2720,6 @@ function getDisplayPartWriter(): DisplayPartsSymbolWriter { increaseIndent: () => { indent++; }, decreaseIndent: () => { indent--; }, clear: resetWriter, - trackSymbol: () => false, - reportInaccessibleThisError: noop, - reportInaccessibleUniqueSymbolError: noop, - reportPrivateInBaseOfClassExpression: noop, }; function writeIndent() { diff --git a/tests/baselines/reference/api/tsserverlibrary.d.ts b/tests/baselines/reference/api/tsserverlibrary.d.ts index ed1562bcdeac1..0af2b39653975 100644 --- a/tests/baselines/reference/api/tsserverlibrary.d.ts +++ b/tests/baselines/reference/api/tsserverlibrary.d.ts @@ -4512,9 +4512,16 @@ declare namespace ts { */ readonly modifiers?: NodeArray | undefined; } - interface JSDocContainer { + interface JSDocContainer extends Node { + _jsdocContainerBrand: any; } - type HasJSDoc = ParameterDeclaration | CallSignatureDeclaration | ClassStaticBlockDeclaration | ConstructSignatureDeclaration | MethodSignature | PropertySignature | ArrowFunction | ParenthesizedExpression | SpreadAssignment | ShorthandPropertyAssignment | PropertyAssignment | FunctionExpression | EmptyStatement | DebuggerStatement | Block | VariableStatement | ExpressionStatement | IfStatement | DoStatement | WhileStatement | ForStatement | ForInStatement | ForOfStatement | BreakStatement | ContinueStatement | ReturnStatement | WithStatement | SwitchStatement | LabeledStatement | ThrowStatement | TryStatement | FunctionDeclaration | ConstructorDeclaration | MethodDeclaration | VariableDeclaration | PropertyDeclaration | AccessorDeclaration | ClassLikeDeclaration | InterfaceDeclaration | TypeAliasDeclaration | EnumMember | EnumDeclaration | ModuleDeclaration | ImportEqualsDeclaration | ImportDeclaration | NamespaceExportDeclaration | ExportAssignment | IndexSignatureDeclaration | FunctionTypeNode | ConstructorTypeNode | JSDocFunctionType | ExportDeclaration | NamedTupleMember | ExportSpecifier | CaseClause | EndOfFileToken; + interface LocalsContainer extends Node { + _localsContainerBrand: any; + } + interface FlowContainer extends Node { + _flowContainerBrand: any; + } + type HasJSDoc = AccessorDeclaration | ArrowFunction | BinaryExpression | Block | BreakStatement | CallSignatureDeclaration | CaseClause | ClassLikeDeclaration | ClassStaticBlockDeclaration | ConstructorDeclaration | ConstructorTypeNode | ConstructSignatureDeclaration | ContinueStatement | DebuggerStatement | DoStatement | ElementAccessExpression | EmptyStatement | EndOfFileToken | EnumDeclaration | EnumMember | ExportAssignment | ExportDeclaration | ExportSpecifier | ExpressionStatement | ForInStatement | ForOfStatement | ForStatement | FunctionDeclaration | FunctionExpression | FunctionTypeNode | Identifier | IfStatement | ImportDeclaration | ImportEqualsDeclaration | IndexSignatureDeclaration | InterfaceDeclaration | JSDocFunctionType | JSDocSignature | LabeledStatement | MethodDeclaration | MethodSignature | ModuleDeclaration | NamedTupleMember | NamespaceExportDeclaration | ObjectLiteralExpression | ParameterDeclaration | ParenthesizedExpression | PropertyAccessExpression | PropertyAssignment | PropertyDeclaration | PropertySignature | ReturnStatement | ShorthandPropertyAssignment | SpreadAssignment | SwitchStatement | ThrowStatement | TryStatement | TypeAliasDeclaration | TypeParameterDeclaration | VariableDeclaration | VariableStatement | WhileStatement | WithStatement; type HasType = SignatureDeclaration | VariableDeclaration | ParameterDeclaration | PropertySignature | PropertyDeclaration | TypePredicateNode | ParenthesizedTypeNode | TypeOperatorNode | MappedTypeNode | AssertionExpression | TypeAliasDeclaration | JSDocTypeExpression | JSDocNonNullableType | JSDocNullableType | JSDocOptionalType | JSDocVariadicType; type HasTypeArguments = CallExpression | NewExpression | TaggedTemplateExpression | JsxOpeningElement | JsxSelfClosingElement; type HasInitializer = HasExpressionInitializer | ForStatement | ForInStatement | ForOfStatement | JsxAttribute; @@ -4582,7 +4589,7 @@ declare namespace ts { FileLevel = 32, AllowNameSubstitution = 64 } - interface Identifier extends PrimaryExpression, Declaration { + interface Identifier extends PrimaryExpression, Declaration, JSDocContainer, FlowContainer { readonly kind: SyntaxKind.Identifier; /** * Prefer to use `id.unescapedText`. (Note: This is available only in services, not internally to the TypeScript compiler.) @@ -4598,7 +4605,7 @@ declare namespace ts { interface TransientIdentifier extends Identifier { resolvedSymbol: Symbol; } - interface QualifiedName extends Node { + interface QualifiedName extends Node, FlowContainer { readonly kind: SyntaxKind.QualifiedName; readonly left: EntityName; readonly right: Identifier; @@ -4633,7 +4640,7 @@ declare namespace ts { readonly parent: NamedDeclaration; readonly expression: LeftHandSideExpression; } - interface TypeParameterDeclaration extends NamedDeclaration { + interface TypeParameterDeclaration extends NamedDeclaration, JSDocContainer { readonly kind: SyntaxKind.TypeParameter; readonly parent: DeclarationWithTypeParameterChildren | InferTypeNode; readonly modifiers?: NodeArray; @@ -4651,10 +4658,10 @@ declare namespace ts { readonly type?: TypeNode | undefined; } type SignatureDeclaration = CallSignatureDeclaration | ConstructSignatureDeclaration | MethodSignature | IndexSignatureDeclaration | FunctionTypeNode | ConstructorTypeNode | JSDocFunctionType | FunctionDeclaration | MethodDeclaration | ConstructorDeclaration | AccessorDeclaration | FunctionExpression | ArrowFunction; - interface CallSignatureDeclaration extends SignatureDeclarationBase, TypeElement { + interface CallSignatureDeclaration extends SignatureDeclarationBase, TypeElement, LocalsContainer { readonly kind: SyntaxKind.CallSignature; } - interface ConstructSignatureDeclaration extends SignatureDeclarationBase, TypeElement { + interface ConstructSignatureDeclaration extends SignatureDeclarationBase, TypeElement, LocalsContainer { readonly kind: SyntaxKind.ConstructSignature; } type BindingName = Identifier | BindingPattern; @@ -4681,7 +4688,7 @@ declare namespace ts { readonly type?: TypeNode; readonly initializer?: Expression; } - interface BindingElement extends NamedDeclaration { + interface BindingElement extends NamedDeclaration, FlowContainer { readonly kind: SyntaxKind.BindingElement; readonly parent: BindingPattern; readonly propertyName?: PropertyName; @@ -4691,6 +4698,7 @@ declare namespace ts { } interface PropertySignature extends TypeElement, JSDocContainer { readonly kind: SyntaxKind.PropertySignature; + readonly parent: TypeLiteralNode | InterfaceDeclaration; readonly modifiers?: NodeArray; readonly name: PropertyName; readonly questionToken?: QuestionToken; @@ -4752,9 +4760,6 @@ declare namespace ts { readonly expression: Expression; } type VariableLikeDeclaration = VariableDeclaration | ParameterDeclaration | BindingElement | PropertyDeclaration | PropertyAssignment | PropertySignature | JsxAttribute | ShorthandPropertyAssignment | EnumMember | JSDocPropertyTag | JSDocParameterTag; - interface PropertyLikeDeclaration extends NamedDeclaration { - readonly name: PropertyName; - } interface ObjectBindingPattern extends Node { readonly kind: SyntaxKind.ObjectBindingPattern; readonly parent: VariableDeclaration | ParameterDeclaration | BindingElement; @@ -4785,26 +4790,26 @@ declare namespace ts { type FunctionLikeDeclaration = FunctionDeclaration | MethodDeclaration | GetAccessorDeclaration | SetAccessorDeclaration | ConstructorDeclaration | FunctionExpression | ArrowFunction; /** @deprecated Use SignatureDeclaration */ type FunctionLike = SignatureDeclaration; - interface FunctionDeclaration extends FunctionLikeDeclarationBase, DeclarationStatement { + interface FunctionDeclaration extends FunctionLikeDeclarationBase, DeclarationStatement, LocalsContainer { readonly kind: SyntaxKind.FunctionDeclaration; readonly modifiers?: NodeArray; readonly name?: Identifier; readonly body?: FunctionBody; } - interface MethodSignature extends SignatureDeclarationBase, TypeElement { + interface MethodSignature extends SignatureDeclarationBase, TypeElement, LocalsContainer { readonly kind: SyntaxKind.MethodSignature; - readonly parent: ObjectTypeDeclaration; + readonly parent: TypeLiteralNode | InterfaceDeclaration; readonly modifiers?: NodeArray; readonly name: PropertyName; } - interface MethodDeclaration extends FunctionLikeDeclarationBase, ClassElement, ObjectLiteralElement, JSDocContainer { + interface MethodDeclaration extends FunctionLikeDeclarationBase, ClassElement, ObjectLiteralElement, JSDocContainer, LocalsContainer, FlowContainer { readonly kind: SyntaxKind.MethodDeclaration; readonly parent: ClassLikeDeclaration | ObjectLiteralExpression; readonly modifiers?: NodeArray | undefined; readonly name: PropertyName; readonly body?: FunctionBody | undefined; } - interface ConstructorDeclaration extends FunctionLikeDeclarationBase, ClassElement, JSDocContainer { + interface ConstructorDeclaration extends FunctionLikeDeclarationBase, ClassElement, JSDocContainer, LocalsContainer { readonly kind: SyntaxKind.Constructor; readonly parent: ClassLikeDeclaration; readonly modifiers?: NodeArray | undefined; @@ -4815,14 +4820,14 @@ declare namespace ts { readonly kind: SyntaxKind.SemicolonClassElement; readonly parent: ClassLikeDeclaration; } - interface GetAccessorDeclaration extends FunctionLikeDeclarationBase, ClassElement, TypeElement, ObjectLiteralElement, JSDocContainer { + interface GetAccessorDeclaration extends FunctionLikeDeclarationBase, ClassElement, TypeElement, ObjectLiteralElement, JSDocContainer, LocalsContainer, FlowContainer { readonly kind: SyntaxKind.GetAccessor; readonly parent: ClassLikeDeclaration | ObjectLiteralExpression | TypeLiteralNode | InterfaceDeclaration; readonly modifiers?: NodeArray; readonly name: PropertyName; readonly body?: FunctionBody; } - interface SetAccessorDeclaration extends FunctionLikeDeclarationBase, ClassElement, TypeElement, ObjectLiteralElement, JSDocContainer { + interface SetAccessorDeclaration extends FunctionLikeDeclarationBase, ClassElement, TypeElement, ObjectLiteralElement, JSDocContainer, LocalsContainer, FlowContainer { readonly kind: SyntaxKind.SetAccessor; readonly parent: ClassLikeDeclaration | ObjectLiteralExpression | TypeLiteralNode | InterfaceDeclaration; readonly modifiers?: NodeArray; @@ -4830,13 +4835,13 @@ declare namespace ts { readonly body?: FunctionBody; } type AccessorDeclaration = GetAccessorDeclaration | SetAccessorDeclaration; - interface IndexSignatureDeclaration extends SignatureDeclarationBase, ClassElement, TypeElement { + interface IndexSignatureDeclaration extends SignatureDeclarationBase, ClassElement, TypeElement, LocalsContainer { readonly kind: SyntaxKind.IndexSignature; readonly parent: ObjectTypeDeclaration; readonly modifiers?: NodeArray; readonly type: TypeNode; } - interface ClassStaticBlockDeclaration extends ClassElement, JSDocContainer { + interface ClassStaticBlockDeclaration extends ClassElement, JSDocContainer, LocalsContainer { readonly kind: SyntaxKind.ClassStaticBlockDeclaration; readonly parent: ClassDeclaration | ClassExpression; readonly body: Block; @@ -4868,14 +4873,14 @@ declare namespace ts { readonly kind: SyntaxKind.FunctionType | SyntaxKind.ConstructorType; readonly type: TypeNode; } - interface FunctionTypeNode extends FunctionOrConstructorTypeNodeBase { + interface FunctionTypeNode extends FunctionOrConstructorTypeNodeBase, LocalsContainer { readonly kind: SyntaxKind.FunctionType; } interface FunctionTypeNode { /** @deprecated A function type cannot have modifiers */ readonly modifiers?: NodeArray | undefined; } - interface ConstructorTypeNode extends FunctionOrConstructorTypeNodeBase { + interface ConstructorTypeNode extends FunctionOrConstructorTypeNodeBase, LocalsContainer { readonly kind: SyntaxKind.ConstructorType; readonly modifiers?: NodeArray; } @@ -4910,7 +4915,7 @@ declare namespace ts { readonly kind: SyntaxKind.TupleType; readonly elements: NodeArray; } - interface NamedTupleMember extends TypeNode, JSDocContainer, Declaration { + interface NamedTupleMember extends TypeNode, Declaration, JSDocContainer { readonly kind: SyntaxKind.NamedTupleMember; readonly dotDotDotToken?: Token; readonly name: Identifier; @@ -4934,7 +4939,7 @@ declare namespace ts { readonly kind: SyntaxKind.IntersectionType; readonly types: NodeArray; } - interface ConditionalTypeNode extends TypeNode { + interface ConditionalTypeNode extends TypeNode, LocalsContainer { readonly kind: SyntaxKind.ConditionalType; readonly checkType: TypeNode; readonly extendsType: TypeNode; @@ -4959,7 +4964,7 @@ declare namespace ts { readonly objectType: TypeNode; readonly indexType: TypeNode; } - interface MappedTypeNode extends TypeNode, Declaration { + interface MappedTypeNode extends TypeNode, Declaration, LocalsContainer { readonly kind: SyntaxKind.MappedType; readonly readonlyToken?: ReadonlyKeyword | PlusToken | MinusToken; readonly typeParameter: TypeParameterDeclaration; @@ -5038,10 +5043,10 @@ declare namespace ts { readonly kind: SyntaxKind.FalseKeyword; } type BooleanLiteral = TrueLiteral | FalseLiteral; - interface ThisExpression extends PrimaryExpression { + interface ThisExpression extends PrimaryExpression, FlowContainer { readonly kind: SyntaxKind.ThisKeyword; } - interface SuperExpression extends PrimaryExpression { + interface SuperExpression extends PrimaryExpression, FlowContainer { readonly kind: SyntaxKind.SuperKeyword; } interface ImportExpression extends PrimaryExpression { @@ -5095,7 +5100,7 @@ declare namespace ts { type BinaryOperator = AssignmentOperatorOrHigher | SyntaxKind.CommaToken; type LogicalOrCoalescingAssignmentOperator = SyntaxKind.AmpersandAmpersandEqualsToken | SyntaxKind.BarBarEqualsToken | SyntaxKind.QuestionQuestionEqualsToken; type BinaryOperatorToken = Token; - interface BinaryExpression extends Expression, Declaration { + interface BinaryExpression extends Expression, Declaration, JSDocContainer { readonly kind: SyntaxKind.BinaryExpression; readonly left: Expression; readonly operatorToken: BinaryOperatorToken; @@ -5132,13 +5137,13 @@ declare namespace ts { } type FunctionBody = Block; type ConciseBody = FunctionBody | Expression; - interface FunctionExpression extends PrimaryExpression, FunctionLikeDeclarationBase, JSDocContainer { + interface FunctionExpression extends PrimaryExpression, FunctionLikeDeclarationBase, JSDocContainer, LocalsContainer, FlowContainer { readonly kind: SyntaxKind.FunctionExpression; readonly modifiers?: NodeArray; readonly name?: Identifier; readonly body: FunctionBody; } - interface ArrowFunction extends Expression, FunctionLikeDeclarationBase, JSDocContainer { + interface ArrowFunction extends Expression, FunctionLikeDeclarationBase, JSDocContainer, LocalsContainer, FlowContainer { readonly kind: SyntaxKind.ArrowFunction; readonly modifiers?: NodeArray; readonly equalsGreaterThanToken: EqualsGreaterThanToken; @@ -5225,13 +5230,13 @@ declare namespace ts { interface ObjectLiteralExpressionBase extends PrimaryExpression, Declaration { readonly properties: NodeArray; } - interface ObjectLiteralExpression extends ObjectLiteralExpressionBase { + interface ObjectLiteralExpression extends ObjectLiteralExpressionBase, JSDocContainer { readonly kind: SyntaxKind.ObjectLiteralExpression; } type EntityNameExpression = Identifier | PropertyAccessEntityNameExpression; type EntityNameOrEntityNameExpression = EntityName | EntityNameExpression; type AccessExpression = PropertyAccessExpression | ElementAccessExpression; - interface PropertyAccessExpression extends MemberExpression, NamedDeclaration { + interface PropertyAccessExpression extends MemberExpression, NamedDeclaration, JSDocContainer, FlowContainer { readonly kind: SyntaxKind.PropertyAccessExpression; readonly expression: LeftHandSideExpression; readonly questionDotToken?: QuestionDotToken; @@ -5250,7 +5255,7 @@ declare namespace ts { readonly expression: EntityNameExpression; readonly name: Identifier; } - interface ElementAccessExpression extends MemberExpression { + interface ElementAccessExpression extends MemberExpression, Declaration, JSDocContainer, FlowContainer { readonly kind: SyntaxKind.ElementAccessExpression; readonly expression: LeftHandSideExpression; readonly questionDotToken?: QuestionDotToken; @@ -5320,7 +5325,7 @@ declare namespace ts { interface NonNullChain extends NonNullExpression { _optionalChainBrand: any; } - interface MetaProperty extends PrimaryExpression { + interface MetaProperty extends PrimaryExpression, FlowContainer { readonly kind: SyntaxKind.MetaProperty; readonly keywordToken: SyntaxKind.NewKeyword | SyntaxKind.ImportKeyword; readonly name: Identifier; @@ -5413,7 +5418,7 @@ declare namespace ts { interface EmptyStatement extends Statement { readonly kind: SyntaxKind.EmptyStatement; } - interface DebuggerStatement extends Statement { + interface DebuggerStatement extends Statement, FlowContainer { readonly kind: SyntaxKind.DebuggerStatement; } interface MissingDeclaration extends DeclarationStatement { @@ -5421,20 +5426,20 @@ declare namespace ts { readonly name?: Identifier; } type BlockLike = SourceFile | Block | ModuleBlock | CaseOrDefaultClause; - interface Block extends Statement { + interface Block extends Statement, LocalsContainer { readonly kind: SyntaxKind.Block; readonly statements: NodeArray; } - interface VariableStatement extends Statement { + interface VariableStatement extends Statement, FlowContainer { readonly kind: SyntaxKind.VariableStatement; readonly modifiers?: NodeArray; readonly declarationList: VariableDeclarationList; } - interface ExpressionStatement extends Statement { + interface ExpressionStatement extends Statement, FlowContainer { readonly kind: SyntaxKind.ExpressionStatement; readonly expression: Expression; } - interface IfStatement extends Statement { + interface IfStatement extends Statement, FlowContainer { readonly kind: SyntaxKind.IfStatement; readonly expression: Expression; readonly thenStatement: Statement; @@ -5443,58 +5448,58 @@ declare namespace ts { interface IterationStatement extends Statement { readonly statement: Statement; } - interface DoStatement extends IterationStatement { + interface DoStatement extends IterationStatement, FlowContainer { readonly kind: SyntaxKind.DoStatement; readonly expression: Expression; } - interface WhileStatement extends IterationStatement { + interface WhileStatement extends IterationStatement, FlowContainer { readonly kind: SyntaxKind.WhileStatement; readonly expression: Expression; } type ForInitializer = VariableDeclarationList | Expression; - interface ForStatement extends IterationStatement { + interface ForStatement extends IterationStatement, LocalsContainer, FlowContainer { readonly kind: SyntaxKind.ForStatement; readonly initializer?: ForInitializer; readonly condition?: Expression; readonly incrementor?: Expression; } type ForInOrOfStatement = ForInStatement | ForOfStatement; - interface ForInStatement extends IterationStatement { + interface ForInStatement extends IterationStatement, LocalsContainer, FlowContainer { readonly kind: SyntaxKind.ForInStatement; readonly initializer: ForInitializer; readonly expression: Expression; } - interface ForOfStatement extends IterationStatement { + interface ForOfStatement extends IterationStatement, LocalsContainer, FlowContainer { readonly kind: SyntaxKind.ForOfStatement; readonly awaitModifier?: AwaitKeyword; readonly initializer: ForInitializer; readonly expression: Expression; } - interface BreakStatement extends Statement { + interface BreakStatement extends Statement, FlowContainer { readonly kind: SyntaxKind.BreakStatement; readonly label?: Identifier; } - interface ContinueStatement extends Statement { + interface ContinueStatement extends Statement, FlowContainer { readonly kind: SyntaxKind.ContinueStatement; readonly label?: Identifier; } type BreakOrContinueStatement = BreakStatement | ContinueStatement; - interface ReturnStatement extends Statement { + interface ReturnStatement extends Statement, FlowContainer { readonly kind: SyntaxKind.ReturnStatement; readonly expression?: Expression; } - interface WithStatement extends Statement { + interface WithStatement extends Statement, FlowContainer { readonly kind: SyntaxKind.WithStatement; readonly expression: Expression; readonly statement: Statement; } - interface SwitchStatement extends Statement { + interface SwitchStatement extends Statement, FlowContainer { readonly kind: SyntaxKind.SwitchStatement; readonly expression: Expression; readonly caseBlock: CaseBlock; possiblyExhaustive?: boolean; } - interface CaseBlock extends Node { + interface CaseBlock extends Node, LocalsContainer { readonly kind: SyntaxKind.CaseBlock; readonly parent: SwitchStatement; readonly clauses: NodeArray; @@ -5511,22 +5516,22 @@ declare namespace ts { readonly statements: NodeArray; } type CaseOrDefaultClause = CaseClause | DefaultClause; - interface LabeledStatement extends Statement { + interface LabeledStatement extends Statement, FlowContainer { readonly kind: SyntaxKind.LabeledStatement; readonly label: Identifier; readonly statement: Statement; } - interface ThrowStatement extends Statement { + interface ThrowStatement extends Statement, FlowContainer { readonly kind: SyntaxKind.ThrowStatement; readonly expression: Expression; } - interface TryStatement extends Statement { + interface TryStatement extends Statement, FlowContainer { readonly kind: SyntaxKind.TryStatement; readonly tryBlock: Block; readonly catchClause?: CatchClause; readonly finallyBlock?: Block; } - interface CatchClause extends Node { + interface CatchClause extends Node, LocalsContainer { readonly kind: SyntaxKind.CatchClause; readonly parent: TryStatement; readonly variableDeclaration?: VariableDeclaration; @@ -5576,7 +5581,7 @@ declare namespace ts { readonly token: SyntaxKind.ExtendsKeyword | SyntaxKind.ImplementsKeyword; readonly types: NodeArray; } - interface TypeAliasDeclaration extends DeclarationStatement, JSDocContainer { + interface TypeAliasDeclaration extends DeclarationStatement, JSDocContainer, LocalsContainer { readonly kind: SyntaxKind.TypeAliasDeclaration; readonly modifiers?: NodeArray; readonly name: Identifier; @@ -5597,7 +5602,7 @@ declare namespace ts { } type ModuleName = Identifier | StringLiteral; type ModuleBody = NamespaceBody | JSDocNamespaceBody; - interface ModuleDeclaration extends DeclarationStatement, JSDocContainer { + interface ModuleDeclaration extends DeclarationStatement, JSDocContainer, LocalsContainer { readonly kind: SyntaxKind.ModuleDeclaration; readonly parent: ModuleBody | SourceFile; readonly modifiers?: NodeArray; @@ -5813,7 +5818,7 @@ declare namespace ts { readonly kind: SyntaxKind.JSDocOptionalType; readonly type: TypeNode; } - interface JSDocFunctionType extends JSDocType, SignatureDeclarationBase { + interface JSDocFunctionType extends JSDocType, SignatureDeclarationBase, LocalsContainer { readonly kind: SyntaxKind.JSDocFunctionType; } interface JSDocVariadicType extends JSDocType { @@ -5899,7 +5904,7 @@ declare namespace ts { interface JSDocOverrideTag extends JSDocTag { readonly kind: SyntaxKind.JSDocOverrideTag; } - interface JSDocEnumTag extends JSDocTag, Declaration { + interface JSDocEnumTag extends JSDocTag, Declaration, LocalsContainer { readonly kind: SyntaxKind.JSDocEnumTag; readonly parent: JSDoc; readonly typeExpression: JSDocTypeExpression; @@ -5925,14 +5930,14 @@ declare namespace ts { readonly kind: SyntaxKind.JSDocTypeTag; readonly typeExpression: JSDocTypeExpression; } - interface JSDocTypedefTag extends JSDocTag, NamedDeclaration { + interface JSDocTypedefTag extends JSDocTag, NamedDeclaration, LocalsContainer { readonly kind: SyntaxKind.JSDocTypedefTag; readonly parent: JSDoc; readonly fullName?: JSDocNamespaceDeclaration | Identifier; readonly name?: Identifier; readonly typeExpression?: JSDocTypeExpression | JSDocTypeLiteral; } - interface JSDocCallbackTag extends JSDocTag, NamedDeclaration { + interface JSDocCallbackTag extends JSDocTag, NamedDeclaration, LocalsContainer { readonly kind: SyntaxKind.JSDocCallbackTag; readonly parent: JSDoc; readonly fullName?: JSDocNamespaceDeclaration | Identifier; @@ -5943,7 +5948,7 @@ declare namespace ts { readonly kind: SyntaxKind.JSDocThrowsTag; readonly typeExpression?: JSDocTypeExpression; } - interface JSDocSignature extends JSDocType, Declaration { + interface JSDocSignature extends JSDocType, Declaration, JSDocContainer, LocalsContainer { readonly kind: SyntaxKind.JSDocSignature; readonly typeParameters?: readonly JSDocTemplateTag[]; readonly parameters: readonly JSDocParameterTag[]; @@ -5963,7 +5968,7 @@ declare namespace ts { interface JSDocParameterTag extends JSDocPropertyLikeTag { readonly kind: SyntaxKind.JSDocParameterTag; } - interface JSDocTypeLiteral extends JSDocType { + interface JSDocTypeLiteral extends JSDocType, Declaration { readonly kind: SyntaxKind.JSDocTypeLiteral; readonly jsDocPropertyTags?: readonly JSDocPropertyLikeTag[]; /** If true, then this type literal represents an *array* of its type. */ @@ -6043,7 +6048,7 @@ declare namespace ts { getLineAndCharacterOfPosition(pos: number): LineAndCharacter; } type ResolutionMode = ModuleKind.ESNext | ModuleKind.CommonJS | undefined; - interface SourceFile extends Declaration { + interface SourceFile extends Declaration, LocalsContainer { readonly kind: SyntaxKind.SourceFile; readonly statements: NodeArray; readonly endOfFileToken: Token; @@ -7469,11 +7474,12 @@ declare namespace ts { createToken(token: SyntaxKind.NullKeyword): NullLiteral; createToken(token: SyntaxKind.TrueKeyword): TrueLiteral; createToken(token: SyntaxKind.FalseKeyword): FalseLiteral; + createToken(token: SyntaxKind.EndOfFileToken): EndOfFileToken; + createToken(token: SyntaxKind.Unknown): Token; createToken(token: TKind): PunctuationToken; createToken(token: TKind): KeywordTypeNode; createToken(token: TKind): ModifierToken; createToken(token: TKind): KeywordToken; - createToken(token: TKind): Token; createSuper(): SuperExpression; createThis(): ThisExpression; createNull(): NullLiteral; diff --git a/tests/baselines/reference/api/typescript.d.ts b/tests/baselines/reference/api/typescript.d.ts index 853c3294bead9..eaf5c1e2626fa 100644 --- a/tests/baselines/reference/api/typescript.d.ts +++ b/tests/baselines/reference/api/typescript.d.ts @@ -578,9 +578,16 @@ declare namespace ts { */ readonly modifiers?: NodeArray | undefined; } - interface JSDocContainer { + interface JSDocContainer extends Node { + _jsdocContainerBrand: any; } - type HasJSDoc = ParameterDeclaration | CallSignatureDeclaration | ClassStaticBlockDeclaration | ConstructSignatureDeclaration | MethodSignature | PropertySignature | ArrowFunction | ParenthesizedExpression | SpreadAssignment | ShorthandPropertyAssignment | PropertyAssignment | FunctionExpression | EmptyStatement | DebuggerStatement | Block | VariableStatement | ExpressionStatement | IfStatement | DoStatement | WhileStatement | ForStatement | ForInStatement | ForOfStatement | BreakStatement | ContinueStatement | ReturnStatement | WithStatement | SwitchStatement | LabeledStatement | ThrowStatement | TryStatement | FunctionDeclaration | ConstructorDeclaration | MethodDeclaration | VariableDeclaration | PropertyDeclaration | AccessorDeclaration | ClassLikeDeclaration | InterfaceDeclaration | TypeAliasDeclaration | EnumMember | EnumDeclaration | ModuleDeclaration | ImportEqualsDeclaration | ImportDeclaration | NamespaceExportDeclaration | ExportAssignment | IndexSignatureDeclaration | FunctionTypeNode | ConstructorTypeNode | JSDocFunctionType | ExportDeclaration | NamedTupleMember | ExportSpecifier | CaseClause | EndOfFileToken; + interface LocalsContainer extends Node { + _localsContainerBrand: any; + } + interface FlowContainer extends Node { + _flowContainerBrand: any; + } + type HasJSDoc = AccessorDeclaration | ArrowFunction | BinaryExpression | Block | BreakStatement | CallSignatureDeclaration | CaseClause | ClassLikeDeclaration | ClassStaticBlockDeclaration | ConstructorDeclaration | ConstructorTypeNode | ConstructSignatureDeclaration | ContinueStatement | DebuggerStatement | DoStatement | ElementAccessExpression | EmptyStatement | EndOfFileToken | EnumDeclaration | EnumMember | ExportAssignment | ExportDeclaration | ExportSpecifier | ExpressionStatement | ForInStatement | ForOfStatement | ForStatement | FunctionDeclaration | FunctionExpression | FunctionTypeNode | Identifier | IfStatement | ImportDeclaration | ImportEqualsDeclaration | IndexSignatureDeclaration | InterfaceDeclaration | JSDocFunctionType | JSDocSignature | LabeledStatement | MethodDeclaration | MethodSignature | ModuleDeclaration | NamedTupleMember | NamespaceExportDeclaration | ObjectLiteralExpression | ParameterDeclaration | ParenthesizedExpression | PropertyAccessExpression | PropertyAssignment | PropertyDeclaration | PropertySignature | ReturnStatement | ShorthandPropertyAssignment | SpreadAssignment | SwitchStatement | ThrowStatement | TryStatement | TypeAliasDeclaration | TypeParameterDeclaration | VariableDeclaration | VariableStatement | WhileStatement | WithStatement; type HasType = SignatureDeclaration | VariableDeclaration | ParameterDeclaration | PropertySignature | PropertyDeclaration | TypePredicateNode | ParenthesizedTypeNode | TypeOperatorNode | MappedTypeNode | AssertionExpression | TypeAliasDeclaration | JSDocTypeExpression | JSDocNonNullableType | JSDocNullableType | JSDocOptionalType | JSDocVariadicType; type HasTypeArguments = CallExpression | NewExpression | TaggedTemplateExpression | JsxOpeningElement | JsxSelfClosingElement; type HasInitializer = HasExpressionInitializer | ForStatement | ForInStatement | ForOfStatement | JsxAttribute; @@ -648,7 +655,7 @@ declare namespace ts { FileLevel = 32, AllowNameSubstitution = 64 } - interface Identifier extends PrimaryExpression, Declaration { + interface Identifier extends PrimaryExpression, Declaration, JSDocContainer, FlowContainer { readonly kind: SyntaxKind.Identifier; /** * Prefer to use `id.unescapedText`. (Note: This is available only in services, not internally to the TypeScript compiler.) @@ -664,7 +671,7 @@ declare namespace ts { interface TransientIdentifier extends Identifier { resolvedSymbol: Symbol; } - interface QualifiedName extends Node { + interface QualifiedName extends Node, FlowContainer { readonly kind: SyntaxKind.QualifiedName; readonly left: EntityName; readonly right: Identifier; @@ -699,7 +706,7 @@ declare namespace ts { readonly parent: NamedDeclaration; readonly expression: LeftHandSideExpression; } - interface TypeParameterDeclaration extends NamedDeclaration { + interface TypeParameterDeclaration extends NamedDeclaration, JSDocContainer { readonly kind: SyntaxKind.TypeParameter; readonly parent: DeclarationWithTypeParameterChildren | InferTypeNode; readonly modifiers?: NodeArray; @@ -717,10 +724,10 @@ declare namespace ts { readonly type?: TypeNode | undefined; } type SignatureDeclaration = CallSignatureDeclaration | ConstructSignatureDeclaration | MethodSignature | IndexSignatureDeclaration | FunctionTypeNode | ConstructorTypeNode | JSDocFunctionType | FunctionDeclaration | MethodDeclaration | ConstructorDeclaration | AccessorDeclaration | FunctionExpression | ArrowFunction; - interface CallSignatureDeclaration extends SignatureDeclarationBase, TypeElement { + interface CallSignatureDeclaration extends SignatureDeclarationBase, TypeElement, LocalsContainer { readonly kind: SyntaxKind.CallSignature; } - interface ConstructSignatureDeclaration extends SignatureDeclarationBase, TypeElement { + interface ConstructSignatureDeclaration extends SignatureDeclarationBase, TypeElement, LocalsContainer { readonly kind: SyntaxKind.ConstructSignature; } type BindingName = Identifier | BindingPattern; @@ -747,7 +754,7 @@ declare namespace ts { readonly type?: TypeNode; readonly initializer?: Expression; } - interface BindingElement extends NamedDeclaration { + interface BindingElement extends NamedDeclaration, FlowContainer { readonly kind: SyntaxKind.BindingElement; readonly parent: BindingPattern; readonly propertyName?: PropertyName; @@ -757,6 +764,7 @@ declare namespace ts { } interface PropertySignature extends TypeElement, JSDocContainer { readonly kind: SyntaxKind.PropertySignature; + readonly parent: TypeLiteralNode | InterfaceDeclaration; readonly modifiers?: NodeArray; readonly name: PropertyName; readonly questionToken?: QuestionToken; @@ -818,9 +826,6 @@ declare namespace ts { readonly expression: Expression; } type VariableLikeDeclaration = VariableDeclaration | ParameterDeclaration | BindingElement | PropertyDeclaration | PropertyAssignment | PropertySignature | JsxAttribute | ShorthandPropertyAssignment | EnumMember | JSDocPropertyTag | JSDocParameterTag; - interface PropertyLikeDeclaration extends NamedDeclaration { - readonly name: PropertyName; - } interface ObjectBindingPattern extends Node { readonly kind: SyntaxKind.ObjectBindingPattern; readonly parent: VariableDeclaration | ParameterDeclaration | BindingElement; @@ -851,26 +856,26 @@ declare namespace ts { type FunctionLikeDeclaration = FunctionDeclaration | MethodDeclaration | GetAccessorDeclaration | SetAccessorDeclaration | ConstructorDeclaration | FunctionExpression | ArrowFunction; /** @deprecated Use SignatureDeclaration */ type FunctionLike = SignatureDeclaration; - interface FunctionDeclaration extends FunctionLikeDeclarationBase, DeclarationStatement { + interface FunctionDeclaration extends FunctionLikeDeclarationBase, DeclarationStatement, LocalsContainer { readonly kind: SyntaxKind.FunctionDeclaration; readonly modifiers?: NodeArray; readonly name?: Identifier; readonly body?: FunctionBody; } - interface MethodSignature extends SignatureDeclarationBase, TypeElement { + interface MethodSignature extends SignatureDeclarationBase, TypeElement, LocalsContainer { readonly kind: SyntaxKind.MethodSignature; - readonly parent: ObjectTypeDeclaration; + readonly parent: TypeLiteralNode | InterfaceDeclaration; readonly modifiers?: NodeArray; readonly name: PropertyName; } - interface MethodDeclaration extends FunctionLikeDeclarationBase, ClassElement, ObjectLiteralElement, JSDocContainer { + interface MethodDeclaration extends FunctionLikeDeclarationBase, ClassElement, ObjectLiteralElement, JSDocContainer, LocalsContainer, FlowContainer { readonly kind: SyntaxKind.MethodDeclaration; readonly parent: ClassLikeDeclaration | ObjectLiteralExpression; readonly modifiers?: NodeArray | undefined; readonly name: PropertyName; readonly body?: FunctionBody | undefined; } - interface ConstructorDeclaration extends FunctionLikeDeclarationBase, ClassElement, JSDocContainer { + interface ConstructorDeclaration extends FunctionLikeDeclarationBase, ClassElement, JSDocContainer, LocalsContainer { readonly kind: SyntaxKind.Constructor; readonly parent: ClassLikeDeclaration; readonly modifiers?: NodeArray | undefined; @@ -881,14 +886,14 @@ declare namespace ts { readonly kind: SyntaxKind.SemicolonClassElement; readonly parent: ClassLikeDeclaration; } - interface GetAccessorDeclaration extends FunctionLikeDeclarationBase, ClassElement, TypeElement, ObjectLiteralElement, JSDocContainer { + interface GetAccessorDeclaration extends FunctionLikeDeclarationBase, ClassElement, TypeElement, ObjectLiteralElement, JSDocContainer, LocalsContainer, FlowContainer { readonly kind: SyntaxKind.GetAccessor; readonly parent: ClassLikeDeclaration | ObjectLiteralExpression | TypeLiteralNode | InterfaceDeclaration; readonly modifiers?: NodeArray; readonly name: PropertyName; readonly body?: FunctionBody; } - interface SetAccessorDeclaration extends FunctionLikeDeclarationBase, ClassElement, TypeElement, ObjectLiteralElement, JSDocContainer { + interface SetAccessorDeclaration extends FunctionLikeDeclarationBase, ClassElement, TypeElement, ObjectLiteralElement, JSDocContainer, LocalsContainer, FlowContainer { readonly kind: SyntaxKind.SetAccessor; readonly parent: ClassLikeDeclaration | ObjectLiteralExpression | TypeLiteralNode | InterfaceDeclaration; readonly modifiers?: NodeArray; @@ -896,13 +901,13 @@ declare namespace ts { readonly body?: FunctionBody; } type AccessorDeclaration = GetAccessorDeclaration | SetAccessorDeclaration; - interface IndexSignatureDeclaration extends SignatureDeclarationBase, ClassElement, TypeElement { + interface IndexSignatureDeclaration extends SignatureDeclarationBase, ClassElement, TypeElement, LocalsContainer { readonly kind: SyntaxKind.IndexSignature; readonly parent: ObjectTypeDeclaration; readonly modifiers?: NodeArray; readonly type: TypeNode; } - interface ClassStaticBlockDeclaration extends ClassElement, JSDocContainer { + interface ClassStaticBlockDeclaration extends ClassElement, JSDocContainer, LocalsContainer { readonly kind: SyntaxKind.ClassStaticBlockDeclaration; readonly parent: ClassDeclaration | ClassExpression; readonly body: Block; @@ -934,14 +939,14 @@ declare namespace ts { readonly kind: SyntaxKind.FunctionType | SyntaxKind.ConstructorType; readonly type: TypeNode; } - interface FunctionTypeNode extends FunctionOrConstructorTypeNodeBase { + interface FunctionTypeNode extends FunctionOrConstructorTypeNodeBase, LocalsContainer { readonly kind: SyntaxKind.FunctionType; } interface FunctionTypeNode { /** @deprecated A function type cannot have modifiers */ readonly modifiers?: NodeArray | undefined; } - interface ConstructorTypeNode extends FunctionOrConstructorTypeNodeBase { + interface ConstructorTypeNode extends FunctionOrConstructorTypeNodeBase, LocalsContainer { readonly kind: SyntaxKind.ConstructorType; readonly modifiers?: NodeArray; } @@ -976,7 +981,7 @@ declare namespace ts { readonly kind: SyntaxKind.TupleType; readonly elements: NodeArray; } - interface NamedTupleMember extends TypeNode, JSDocContainer, Declaration { + interface NamedTupleMember extends TypeNode, Declaration, JSDocContainer { readonly kind: SyntaxKind.NamedTupleMember; readonly dotDotDotToken?: Token; readonly name: Identifier; @@ -1000,7 +1005,7 @@ declare namespace ts { readonly kind: SyntaxKind.IntersectionType; readonly types: NodeArray; } - interface ConditionalTypeNode extends TypeNode { + interface ConditionalTypeNode extends TypeNode, LocalsContainer { readonly kind: SyntaxKind.ConditionalType; readonly checkType: TypeNode; readonly extendsType: TypeNode; @@ -1025,7 +1030,7 @@ declare namespace ts { readonly objectType: TypeNode; readonly indexType: TypeNode; } - interface MappedTypeNode extends TypeNode, Declaration { + interface MappedTypeNode extends TypeNode, Declaration, LocalsContainer { readonly kind: SyntaxKind.MappedType; readonly readonlyToken?: ReadonlyKeyword | PlusToken | MinusToken; readonly typeParameter: TypeParameterDeclaration; @@ -1104,10 +1109,10 @@ declare namespace ts { readonly kind: SyntaxKind.FalseKeyword; } type BooleanLiteral = TrueLiteral | FalseLiteral; - interface ThisExpression extends PrimaryExpression { + interface ThisExpression extends PrimaryExpression, FlowContainer { readonly kind: SyntaxKind.ThisKeyword; } - interface SuperExpression extends PrimaryExpression { + interface SuperExpression extends PrimaryExpression, FlowContainer { readonly kind: SyntaxKind.SuperKeyword; } interface ImportExpression extends PrimaryExpression { @@ -1161,7 +1166,7 @@ declare namespace ts { type BinaryOperator = AssignmentOperatorOrHigher | SyntaxKind.CommaToken; type LogicalOrCoalescingAssignmentOperator = SyntaxKind.AmpersandAmpersandEqualsToken | SyntaxKind.BarBarEqualsToken | SyntaxKind.QuestionQuestionEqualsToken; type BinaryOperatorToken = Token; - interface BinaryExpression extends Expression, Declaration { + interface BinaryExpression extends Expression, Declaration, JSDocContainer { readonly kind: SyntaxKind.BinaryExpression; readonly left: Expression; readonly operatorToken: BinaryOperatorToken; @@ -1198,13 +1203,13 @@ declare namespace ts { } type FunctionBody = Block; type ConciseBody = FunctionBody | Expression; - interface FunctionExpression extends PrimaryExpression, FunctionLikeDeclarationBase, JSDocContainer { + interface FunctionExpression extends PrimaryExpression, FunctionLikeDeclarationBase, JSDocContainer, LocalsContainer, FlowContainer { readonly kind: SyntaxKind.FunctionExpression; readonly modifiers?: NodeArray; readonly name?: Identifier; readonly body: FunctionBody; } - interface ArrowFunction extends Expression, FunctionLikeDeclarationBase, JSDocContainer { + interface ArrowFunction extends Expression, FunctionLikeDeclarationBase, JSDocContainer, LocalsContainer, FlowContainer { readonly kind: SyntaxKind.ArrowFunction; readonly modifiers?: NodeArray; readonly equalsGreaterThanToken: EqualsGreaterThanToken; @@ -1291,13 +1296,13 @@ declare namespace ts { interface ObjectLiteralExpressionBase extends PrimaryExpression, Declaration { readonly properties: NodeArray; } - interface ObjectLiteralExpression extends ObjectLiteralExpressionBase { + interface ObjectLiteralExpression extends ObjectLiteralExpressionBase, JSDocContainer { readonly kind: SyntaxKind.ObjectLiteralExpression; } type EntityNameExpression = Identifier | PropertyAccessEntityNameExpression; type EntityNameOrEntityNameExpression = EntityName | EntityNameExpression; type AccessExpression = PropertyAccessExpression | ElementAccessExpression; - interface PropertyAccessExpression extends MemberExpression, NamedDeclaration { + interface PropertyAccessExpression extends MemberExpression, NamedDeclaration, JSDocContainer, FlowContainer { readonly kind: SyntaxKind.PropertyAccessExpression; readonly expression: LeftHandSideExpression; readonly questionDotToken?: QuestionDotToken; @@ -1316,7 +1321,7 @@ declare namespace ts { readonly expression: EntityNameExpression; readonly name: Identifier; } - interface ElementAccessExpression extends MemberExpression { + interface ElementAccessExpression extends MemberExpression, Declaration, JSDocContainer, FlowContainer { readonly kind: SyntaxKind.ElementAccessExpression; readonly expression: LeftHandSideExpression; readonly questionDotToken?: QuestionDotToken; @@ -1386,7 +1391,7 @@ declare namespace ts { interface NonNullChain extends NonNullExpression { _optionalChainBrand: any; } - interface MetaProperty extends PrimaryExpression { + interface MetaProperty extends PrimaryExpression, FlowContainer { readonly kind: SyntaxKind.MetaProperty; readonly keywordToken: SyntaxKind.NewKeyword | SyntaxKind.ImportKeyword; readonly name: Identifier; @@ -1479,7 +1484,7 @@ declare namespace ts { interface EmptyStatement extends Statement { readonly kind: SyntaxKind.EmptyStatement; } - interface DebuggerStatement extends Statement { + interface DebuggerStatement extends Statement, FlowContainer { readonly kind: SyntaxKind.DebuggerStatement; } interface MissingDeclaration extends DeclarationStatement { @@ -1487,20 +1492,20 @@ declare namespace ts { readonly name?: Identifier; } type BlockLike = SourceFile | Block | ModuleBlock | CaseOrDefaultClause; - interface Block extends Statement { + interface Block extends Statement, LocalsContainer { readonly kind: SyntaxKind.Block; readonly statements: NodeArray; } - interface VariableStatement extends Statement { + interface VariableStatement extends Statement, FlowContainer { readonly kind: SyntaxKind.VariableStatement; readonly modifiers?: NodeArray; readonly declarationList: VariableDeclarationList; } - interface ExpressionStatement extends Statement { + interface ExpressionStatement extends Statement, FlowContainer { readonly kind: SyntaxKind.ExpressionStatement; readonly expression: Expression; } - interface IfStatement extends Statement { + interface IfStatement extends Statement, FlowContainer { readonly kind: SyntaxKind.IfStatement; readonly expression: Expression; readonly thenStatement: Statement; @@ -1509,58 +1514,58 @@ declare namespace ts { interface IterationStatement extends Statement { readonly statement: Statement; } - interface DoStatement extends IterationStatement { + interface DoStatement extends IterationStatement, FlowContainer { readonly kind: SyntaxKind.DoStatement; readonly expression: Expression; } - interface WhileStatement extends IterationStatement { + interface WhileStatement extends IterationStatement, FlowContainer { readonly kind: SyntaxKind.WhileStatement; readonly expression: Expression; } type ForInitializer = VariableDeclarationList | Expression; - interface ForStatement extends IterationStatement { + interface ForStatement extends IterationStatement, LocalsContainer, FlowContainer { readonly kind: SyntaxKind.ForStatement; readonly initializer?: ForInitializer; readonly condition?: Expression; readonly incrementor?: Expression; } type ForInOrOfStatement = ForInStatement | ForOfStatement; - interface ForInStatement extends IterationStatement { + interface ForInStatement extends IterationStatement, LocalsContainer, FlowContainer { readonly kind: SyntaxKind.ForInStatement; readonly initializer: ForInitializer; readonly expression: Expression; } - interface ForOfStatement extends IterationStatement { + interface ForOfStatement extends IterationStatement, LocalsContainer, FlowContainer { readonly kind: SyntaxKind.ForOfStatement; readonly awaitModifier?: AwaitKeyword; readonly initializer: ForInitializer; readonly expression: Expression; } - interface BreakStatement extends Statement { + interface BreakStatement extends Statement, FlowContainer { readonly kind: SyntaxKind.BreakStatement; readonly label?: Identifier; } - interface ContinueStatement extends Statement { + interface ContinueStatement extends Statement, FlowContainer { readonly kind: SyntaxKind.ContinueStatement; readonly label?: Identifier; } type BreakOrContinueStatement = BreakStatement | ContinueStatement; - interface ReturnStatement extends Statement { + interface ReturnStatement extends Statement, FlowContainer { readonly kind: SyntaxKind.ReturnStatement; readonly expression?: Expression; } - interface WithStatement extends Statement { + interface WithStatement extends Statement, FlowContainer { readonly kind: SyntaxKind.WithStatement; readonly expression: Expression; readonly statement: Statement; } - interface SwitchStatement extends Statement { + interface SwitchStatement extends Statement, FlowContainer { readonly kind: SyntaxKind.SwitchStatement; readonly expression: Expression; readonly caseBlock: CaseBlock; possiblyExhaustive?: boolean; } - interface CaseBlock extends Node { + interface CaseBlock extends Node, LocalsContainer { readonly kind: SyntaxKind.CaseBlock; readonly parent: SwitchStatement; readonly clauses: NodeArray; @@ -1577,22 +1582,22 @@ declare namespace ts { readonly statements: NodeArray; } type CaseOrDefaultClause = CaseClause | DefaultClause; - interface LabeledStatement extends Statement { + interface LabeledStatement extends Statement, FlowContainer { readonly kind: SyntaxKind.LabeledStatement; readonly label: Identifier; readonly statement: Statement; } - interface ThrowStatement extends Statement { + interface ThrowStatement extends Statement, FlowContainer { readonly kind: SyntaxKind.ThrowStatement; readonly expression: Expression; } - interface TryStatement extends Statement { + interface TryStatement extends Statement, FlowContainer { readonly kind: SyntaxKind.TryStatement; readonly tryBlock: Block; readonly catchClause?: CatchClause; readonly finallyBlock?: Block; } - interface CatchClause extends Node { + interface CatchClause extends Node, LocalsContainer { readonly kind: SyntaxKind.CatchClause; readonly parent: TryStatement; readonly variableDeclaration?: VariableDeclaration; @@ -1642,7 +1647,7 @@ declare namespace ts { readonly token: SyntaxKind.ExtendsKeyword | SyntaxKind.ImplementsKeyword; readonly types: NodeArray; } - interface TypeAliasDeclaration extends DeclarationStatement, JSDocContainer { + interface TypeAliasDeclaration extends DeclarationStatement, JSDocContainer, LocalsContainer { readonly kind: SyntaxKind.TypeAliasDeclaration; readonly modifiers?: NodeArray; readonly name: Identifier; @@ -1663,7 +1668,7 @@ declare namespace ts { } type ModuleName = Identifier | StringLiteral; type ModuleBody = NamespaceBody | JSDocNamespaceBody; - interface ModuleDeclaration extends DeclarationStatement, JSDocContainer { + interface ModuleDeclaration extends DeclarationStatement, JSDocContainer, LocalsContainer { readonly kind: SyntaxKind.ModuleDeclaration; readonly parent: ModuleBody | SourceFile; readonly modifiers?: NodeArray; @@ -1879,7 +1884,7 @@ declare namespace ts { readonly kind: SyntaxKind.JSDocOptionalType; readonly type: TypeNode; } - interface JSDocFunctionType extends JSDocType, SignatureDeclarationBase { + interface JSDocFunctionType extends JSDocType, SignatureDeclarationBase, LocalsContainer { readonly kind: SyntaxKind.JSDocFunctionType; } interface JSDocVariadicType extends JSDocType { @@ -1965,7 +1970,7 @@ declare namespace ts { interface JSDocOverrideTag extends JSDocTag { readonly kind: SyntaxKind.JSDocOverrideTag; } - interface JSDocEnumTag extends JSDocTag, Declaration { + interface JSDocEnumTag extends JSDocTag, Declaration, LocalsContainer { readonly kind: SyntaxKind.JSDocEnumTag; readonly parent: JSDoc; readonly typeExpression: JSDocTypeExpression; @@ -1991,14 +1996,14 @@ declare namespace ts { readonly kind: SyntaxKind.JSDocTypeTag; readonly typeExpression: JSDocTypeExpression; } - interface JSDocTypedefTag extends JSDocTag, NamedDeclaration { + interface JSDocTypedefTag extends JSDocTag, NamedDeclaration, LocalsContainer { readonly kind: SyntaxKind.JSDocTypedefTag; readonly parent: JSDoc; readonly fullName?: JSDocNamespaceDeclaration | Identifier; readonly name?: Identifier; readonly typeExpression?: JSDocTypeExpression | JSDocTypeLiteral; } - interface JSDocCallbackTag extends JSDocTag, NamedDeclaration { + interface JSDocCallbackTag extends JSDocTag, NamedDeclaration, LocalsContainer { readonly kind: SyntaxKind.JSDocCallbackTag; readonly parent: JSDoc; readonly fullName?: JSDocNamespaceDeclaration | Identifier; @@ -2009,7 +2014,7 @@ declare namespace ts { readonly kind: SyntaxKind.JSDocThrowsTag; readonly typeExpression?: JSDocTypeExpression; } - interface JSDocSignature extends JSDocType, Declaration { + interface JSDocSignature extends JSDocType, Declaration, JSDocContainer, LocalsContainer { readonly kind: SyntaxKind.JSDocSignature; readonly typeParameters?: readonly JSDocTemplateTag[]; readonly parameters: readonly JSDocParameterTag[]; @@ -2029,7 +2034,7 @@ declare namespace ts { interface JSDocParameterTag extends JSDocPropertyLikeTag { readonly kind: SyntaxKind.JSDocParameterTag; } - interface JSDocTypeLiteral extends JSDocType { + interface JSDocTypeLiteral extends JSDocType, Declaration { readonly kind: SyntaxKind.JSDocTypeLiteral; readonly jsDocPropertyTags?: readonly JSDocPropertyLikeTag[]; /** If true, then this type literal represents an *array* of its type. */ @@ -2109,7 +2114,7 @@ declare namespace ts { getLineAndCharacterOfPosition(pos: number): LineAndCharacter; } type ResolutionMode = ModuleKind.ESNext | ModuleKind.CommonJS | undefined; - interface SourceFile extends Declaration { + interface SourceFile extends Declaration, LocalsContainer { readonly kind: SyntaxKind.SourceFile; readonly statements: NodeArray; readonly endOfFileToken: Token; @@ -3535,11 +3540,12 @@ declare namespace ts { createToken(token: SyntaxKind.NullKeyword): NullLiteral; createToken(token: SyntaxKind.TrueKeyword): TrueLiteral; createToken(token: SyntaxKind.FalseKeyword): FalseLiteral; + createToken(token: SyntaxKind.EndOfFileToken): EndOfFileToken; + createToken(token: SyntaxKind.Unknown): Token; createToken(token: TKind): PunctuationToken; createToken(token: TKind): KeywordTypeNode; createToken(token: TKind): ModifierToken; createToken(token: TKind): KeywordToken; - createToken(token: TKind): Token; createSuper(): SuperExpression; createThis(): ThisExpression; createNull(): NullLiteral; diff --git a/tests/baselines/reference/computedPropertyNames21_ES5.symbols b/tests/baselines/reference/computedPropertyNames21_ES5.symbols index 16cba36da92f7..87f95d73a67de 100644 --- a/tests/baselines/reference/computedPropertyNames21_ES5.symbols +++ b/tests/baselines/reference/computedPropertyNames21_ES5.symbols @@ -9,4 +9,7 @@ class C { } [this.bar()]() { } >[this.bar()] : Symbol(C[this.bar()], Decl(computedPropertyNames21_ES5.ts, 3, 5)) +>this.bar : Symbol(C.bar, Decl(computedPropertyNames21_ES5.ts, 0, 9)) +>this : Symbol(C, Decl(computedPropertyNames21_ES5.ts, 0, 0)) +>bar : Symbol(C.bar, Decl(computedPropertyNames21_ES5.ts, 0, 9)) } diff --git a/tests/baselines/reference/computedPropertyNames21_ES5.types b/tests/baselines/reference/computedPropertyNames21_ES5.types index 09a15e0d912af..e2b2689aa0579 100644 --- a/tests/baselines/reference/computedPropertyNames21_ES5.types +++ b/tests/baselines/reference/computedPropertyNames21_ES5.types @@ -10,8 +10,8 @@ class C { } [this.bar()]() { } >[this.bar()] : () => void ->this.bar() : any ->this.bar : any ->this : any ->bar : any +>this.bar() : number +>this.bar : () => number +>this : this +>bar : () => number } diff --git a/tests/baselines/reference/computedPropertyNames21_ES6.symbols b/tests/baselines/reference/computedPropertyNames21_ES6.symbols index 484307748b172..2efed9baca87a 100644 --- a/tests/baselines/reference/computedPropertyNames21_ES6.symbols +++ b/tests/baselines/reference/computedPropertyNames21_ES6.symbols @@ -9,4 +9,7 @@ class C { } [this.bar()]() { } >[this.bar()] : Symbol(C[this.bar()], Decl(computedPropertyNames21_ES6.ts, 3, 5)) +>this.bar : Symbol(C.bar, Decl(computedPropertyNames21_ES6.ts, 0, 9)) +>this : Symbol(C, Decl(computedPropertyNames21_ES6.ts, 0, 0)) +>bar : Symbol(C.bar, Decl(computedPropertyNames21_ES6.ts, 0, 9)) } diff --git a/tests/baselines/reference/computedPropertyNames21_ES6.types b/tests/baselines/reference/computedPropertyNames21_ES6.types index 33587d08ae640..86a247bd9ab8b 100644 --- a/tests/baselines/reference/computedPropertyNames21_ES6.types +++ b/tests/baselines/reference/computedPropertyNames21_ES6.types @@ -10,8 +10,8 @@ class C { } [this.bar()]() { } >[this.bar()] : () => void ->this.bar() : any ->this.bar : any ->this : any ->bar : any +>this.bar() : number +>this.bar : () => number +>this : this +>bar : () => number } diff --git a/tests/baselines/reference/computedPropertyNames23_ES5.symbols b/tests/baselines/reference/computedPropertyNames23_ES5.symbols index 8ba4c63ae901a..5c13517193c82 100644 --- a/tests/baselines/reference/computedPropertyNames23_ES5.symbols +++ b/tests/baselines/reference/computedPropertyNames23_ES5.symbols @@ -14,6 +14,9 @@ class C { { [this.bar()]: 1 }[0] >[this.bar()] : Symbol([this.bar()], Decl(computedPropertyNames23_ES5.ts, 5, 9)) +>this.bar : Symbol(C.bar, Decl(computedPropertyNames23_ES5.ts, 0, 9)) +>this : Symbol(C, Decl(computedPropertyNames23_ES5.ts, 0, 0)) +>bar : Symbol(C.bar, Decl(computedPropertyNames23_ES5.ts, 0, 9)) ]() { } } diff --git a/tests/baselines/reference/computedPropertyNames23_ES5.types b/tests/baselines/reference/computedPropertyNames23_ES5.types index 7090bfa3ba9a0..82a2c93ef50c5 100644 --- a/tests/baselines/reference/computedPropertyNames23_ES5.types +++ b/tests/baselines/reference/computedPropertyNames23_ES5.types @@ -15,10 +15,10 @@ class C { >{ [this.bar()]: 1 }[0] : number >{ [this.bar()]: 1 } : { [x: number]: number; } >[this.bar()] : number ->this.bar() : any ->this.bar : any ->this : any ->bar : any +>this.bar() : number +>this.bar : () => number +>this : this +>bar : () => number >1 : 1 >0 : 0 diff --git a/tests/baselines/reference/computedPropertyNames23_ES6.symbols b/tests/baselines/reference/computedPropertyNames23_ES6.symbols index d402d8cc7ac49..945226a4e1666 100644 --- a/tests/baselines/reference/computedPropertyNames23_ES6.symbols +++ b/tests/baselines/reference/computedPropertyNames23_ES6.symbols @@ -14,6 +14,9 @@ class C { { [this.bar()]: 1 }[0] >[this.bar()] : Symbol([this.bar()], Decl(computedPropertyNames23_ES6.ts, 5, 9)) +>this.bar : Symbol(C.bar, Decl(computedPropertyNames23_ES6.ts, 0, 9)) +>this : Symbol(C, Decl(computedPropertyNames23_ES6.ts, 0, 0)) +>bar : Symbol(C.bar, Decl(computedPropertyNames23_ES6.ts, 0, 9)) ]() { } } diff --git a/tests/baselines/reference/computedPropertyNames23_ES6.types b/tests/baselines/reference/computedPropertyNames23_ES6.types index 39133196ed42f..3eba570c39a77 100644 --- a/tests/baselines/reference/computedPropertyNames23_ES6.types +++ b/tests/baselines/reference/computedPropertyNames23_ES6.types @@ -15,10 +15,10 @@ class C { >{ [this.bar()]: 1 }[0] : number >{ [this.bar()]: 1 } : { [x: number]: number; } >[this.bar()] : number ->this.bar() : any ->this.bar : any ->this : any ->bar : any +>this.bar() : number +>this.bar : () => number +>this : this +>bar : () => number >1 : 1 >0 : 0 diff --git a/tests/baselines/reference/typeOfThisInStaticMembers12(target=es2022).errors.txt b/tests/baselines/reference/typeOfThisInStaticMembers12(target=es2022).errors.txt index 3855b2ee7b651..736afd3313057 100644 --- a/tests/baselines/reference/typeOfThisInStaticMembers12(target=es2022).errors.txt +++ b/tests/baselines/reference/typeOfThisInStaticMembers12(target=es2022).errors.txt @@ -1,10 +1,12 @@ tests/cases/conformance/classes/members/instanceAndStaticMembers/typeOfThisInStaticMembers12.ts(4,16): error TS1166: A computed property name in a class property declaration must have a simple literal type or a 'unique symbol' type. tests/cases/conformance/classes/members/instanceAndStaticMembers/typeOfThisInStaticMembers12.ts(4,17): error TS2465: 'this' cannot be referenced in a computed property name. +tests/cases/conformance/classes/members/instanceAndStaticMembers/typeOfThisInStaticMembers12.ts(4,22): error TS2339: Property 'c' does not exist on type 'typeof Inner'. tests/cases/conformance/classes/members/instanceAndStaticMembers/typeOfThisInStaticMembers12.ts(5,9): error TS1166: A computed property name in a class property declaration must have a simple literal type or a 'unique symbol' type. tests/cases/conformance/classes/members/instanceAndStaticMembers/typeOfThisInStaticMembers12.ts(5,10): error TS2465: 'this' cannot be referenced in a computed property name. +tests/cases/conformance/classes/members/instanceAndStaticMembers/typeOfThisInStaticMembers12.ts(5,15): error TS2339: Property 'c' does not exist on type 'Inner'. -==== tests/cases/conformance/classes/members/instanceAndStaticMembers/typeOfThisInStaticMembers12.ts (4 errors) ==== +==== tests/cases/conformance/classes/members/instanceAndStaticMembers/typeOfThisInStaticMembers12.ts (6 errors) ==== class C { static readonly c: "foo" = "foo" static bar = class Inner { @@ -13,11 +15,15 @@ tests/cases/conformance/classes/members/instanceAndStaticMembers/typeOfThisInSta !!! error TS1166: A computed property name in a class property declaration must have a simple literal type or a 'unique symbol' type. ~~~~ !!! error TS2465: 'this' cannot be referenced in a computed property name. + ~ +!!! error TS2339: Property 'c' does not exist on type 'typeof Inner'. [this.c] = 123; ~~~~~~~~ !!! error TS1166: A computed property name in a class property declaration must have a simple literal type or a 'unique symbol' type. ~~~~ !!! error TS2465: 'this' cannot be referenced in a computed property name. + ~ +!!! error TS2339: Property 'c' does not exist on type 'Inner'. } } \ No newline at end of file diff --git a/tests/baselines/reference/typeOfThisInStaticMembers12(target=es2022).symbols b/tests/baselines/reference/typeOfThisInStaticMembers12(target=es2022).symbols index 16ad5c64fd0df..6e778e2c523a8 100644 --- a/tests/baselines/reference/typeOfThisInStaticMembers12(target=es2022).symbols +++ b/tests/baselines/reference/typeOfThisInStaticMembers12(target=es2022).symbols @@ -11,9 +11,11 @@ class C { static [this.c] = 123; >[this.c] : Symbol(Inner[this.c], Decl(typeOfThisInStaticMembers12.ts, 2, 31)) +>this : Symbol(Inner, Decl(typeOfThisInStaticMembers12.ts, 2, 16)) [this.c] = 123; >[this.c] : Symbol(Inner[this.c], Decl(typeOfThisInStaticMembers12.ts, 3, 30)) +>this : Symbol(Inner, Decl(typeOfThisInStaticMembers12.ts, 2, 16)) } } diff --git a/tests/baselines/reference/typeOfThisInStaticMembers12(target=es2022).types b/tests/baselines/reference/typeOfThisInStaticMembers12(target=es2022).types index ca37b9e4e200e..539f49702b2b4 100644 --- a/tests/baselines/reference/typeOfThisInStaticMembers12(target=es2022).types +++ b/tests/baselines/reference/typeOfThisInStaticMembers12(target=es2022).types @@ -14,14 +14,14 @@ class C { static [this.c] = 123; >[this.c] : number >this.c : any ->this : any +>this : typeof Inner >c : any >123 : 123 [this.c] = 123; >[this.c] : number >this.c : any ->this : any +>this : this >c : any >123 : 123 } diff --git a/tests/baselines/reference/typeOfThisInStaticMembers12(target=es5).errors.txt b/tests/baselines/reference/typeOfThisInStaticMembers12(target=es5).errors.txt index 3855b2ee7b651..736afd3313057 100644 --- a/tests/baselines/reference/typeOfThisInStaticMembers12(target=es5).errors.txt +++ b/tests/baselines/reference/typeOfThisInStaticMembers12(target=es5).errors.txt @@ -1,10 +1,12 @@ tests/cases/conformance/classes/members/instanceAndStaticMembers/typeOfThisInStaticMembers12.ts(4,16): error TS1166: A computed property name in a class property declaration must have a simple literal type or a 'unique symbol' type. tests/cases/conformance/classes/members/instanceAndStaticMembers/typeOfThisInStaticMembers12.ts(4,17): error TS2465: 'this' cannot be referenced in a computed property name. +tests/cases/conformance/classes/members/instanceAndStaticMembers/typeOfThisInStaticMembers12.ts(4,22): error TS2339: Property 'c' does not exist on type 'typeof Inner'. tests/cases/conformance/classes/members/instanceAndStaticMembers/typeOfThisInStaticMembers12.ts(5,9): error TS1166: A computed property name in a class property declaration must have a simple literal type or a 'unique symbol' type. tests/cases/conformance/classes/members/instanceAndStaticMembers/typeOfThisInStaticMembers12.ts(5,10): error TS2465: 'this' cannot be referenced in a computed property name. +tests/cases/conformance/classes/members/instanceAndStaticMembers/typeOfThisInStaticMembers12.ts(5,15): error TS2339: Property 'c' does not exist on type 'Inner'. -==== tests/cases/conformance/classes/members/instanceAndStaticMembers/typeOfThisInStaticMembers12.ts (4 errors) ==== +==== tests/cases/conformance/classes/members/instanceAndStaticMembers/typeOfThisInStaticMembers12.ts (6 errors) ==== class C { static readonly c: "foo" = "foo" static bar = class Inner { @@ -13,11 +15,15 @@ tests/cases/conformance/classes/members/instanceAndStaticMembers/typeOfThisInSta !!! error TS1166: A computed property name in a class property declaration must have a simple literal type or a 'unique symbol' type. ~~~~ !!! error TS2465: 'this' cannot be referenced in a computed property name. + ~ +!!! error TS2339: Property 'c' does not exist on type 'typeof Inner'. [this.c] = 123; ~~~~~~~~ !!! error TS1166: A computed property name in a class property declaration must have a simple literal type or a 'unique symbol' type. ~~~~ !!! error TS2465: 'this' cannot be referenced in a computed property name. + ~ +!!! error TS2339: Property 'c' does not exist on type 'Inner'. } } \ No newline at end of file diff --git a/tests/baselines/reference/typeOfThisInStaticMembers12(target=es5).symbols b/tests/baselines/reference/typeOfThisInStaticMembers12(target=es5).symbols index 16ad5c64fd0df..6e778e2c523a8 100644 --- a/tests/baselines/reference/typeOfThisInStaticMembers12(target=es5).symbols +++ b/tests/baselines/reference/typeOfThisInStaticMembers12(target=es5).symbols @@ -11,9 +11,11 @@ class C { static [this.c] = 123; >[this.c] : Symbol(Inner[this.c], Decl(typeOfThisInStaticMembers12.ts, 2, 31)) +>this : Symbol(Inner, Decl(typeOfThisInStaticMembers12.ts, 2, 16)) [this.c] = 123; >[this.c] : Symbol(Inner[this.c], Decl(typeOfThisInStaticMembers12.ts, 3, 30)) +>this : Symbol(Inner, Decl(typeOfThisInStaticMembers12.ts, 2, 16)) } } diff --git a/tests/baselines/reference/typeOfThisInStaticMembers12(target=es5).types b/tests/baselines/reference/typeOfThisInStaticMembers12(target=es5).types index ca37b9e4e200e..539f49702b2b4 100644 --- a/tests/baselines/reference/typeOfThisInStaticMembers12(target=es5).types +++ b/tests/baselines/reference/typeOfThisInStaticMembers12(target=es5).types @@ -14,14 +14,14 @@ class C { static [this.c] = 123; >[this.c] : number >this.c : any ->this : any +>this : typeof Inner >c : any >123 : 123 [this.c] = 123; >[this.c] : number >this.c : any ->this : any +>this : this >c : any >123 : 123 } diff --git a/tests/baselines/reference/typeOfThisInStaticMembers12(target=es6).errors.txt b/tests/baselines/reference/typeOfThisInStaticMembers12(target=es6).errors.txt index 3855b2ee7b651..736afd3313057 100644 --- a/tests/baselines/reference/typeOfThisInStaticMembers12(target=es6).errors.txt +++ b/tests/baselines/reference/typeOfThisInStaticMembers12(target=es6).errors.txt @@ -1,10 +1,12 @@ tests/cases/conformance/classes/members/instanceAndStaticMembers/typeOfThisInStaticMembers12.ts(4,16): error TS1166: A computed property name in a class property declaration must have a simple literal type or a 'unique symbol' type. tests/cases/conformance/classes/members/instanceAndStaticMembers/typeOfThisInStaticMembers12.ts(4,17): error TS2465: 'this' cannot be referenced in a computed property name. +tests/cases/conformance/classes/members/instanceAndStaticMembers/typeOfThisInStaticMembers12.ts(4,22): error TS2339: Property 'c' does not exist on type 'typeof Inner'. tests/cases/conformance/classes/members/instanceAndStaticMembers/typeOfThisInStaticMembers12.ts(5,9): error TS1166: A computed property name in a class property declaration must have a simple literal type or a 'unique symbol' type. tests/cases/conformance/classes/members/instanceAndStaticMembers/typeOfThisInStaticMembers12.ts(5,10): error TS2465: 'this' cannot be referenced in a computed property name. +tests/cases/conformance/classes/members/instanceAndStaticMembers/typeOfThisInStaticMembers12.ts(5,15): error TS2339: Property 'c' does not exist on type 'Inner'. -==== tests/cases/conformance/classes/members/instanceAndStaticMembers/typeOfThisInStaticMembers12.ts (4 errors) ==== +==== tests/cases/conformance/classes/members/instanceAndStaticMembers/typeOfThisInStaticMembers12.ts (6 errors) ==== class C { static readonly c: "foo" = "foo" static bar = class Inner { @@ -13,11 +15,15 @@ tests/cases/conformance/classes/members/instanceAndStaticMembers/typeOfThisInSta !!! error TS1166: A computed property name in a class property declaration must have a simple literal type or a 'unique symbol' type. ~~~~ !!! error TS2465: 'this' cannot be referenced in a computed property name. + ~ +!!! error TS2339: Property 'c' does not exist on type 'typeof Inner'. [this.c] = 123; ~~~~~~~~ !!! error TS1166: A computed property name in a class property declaration must have a simple literal type or a 'unique symbol' type. ~~~~ !!! error TS2465: 'this' cannot be referenced in a computed property name. + ~ +!!! error TS2339: Property 'c' does not exist on type 'Inner'. } } \ No newline at end of file diff --git a/tests/baselines/reference/typeOfThisInStaticMembers12(target=es6).symbols b/tests/baselines/reference/typeOfThisInStaticMembers12(target=es6).symbols index 16ad5c64fd0df..6e778e2c523a8 100644 --- a/tests/baselines/reference/typeOfThisInStaticMembers12(target=es6).symbols +++ b/tests/baselines/reference/typeOfThisInStaticMembers12(target=es6).symbols @@ -11,9 +11,11 @@ class C { static [this.c] = 123; >[this.c] : Symbol(Inner[this.c], Decl(typeOfThisInStaticMembers12.ts, 2, 31)) +>this : Symbol(Inner, Decl(typeOfThisInStaticMembers12.ts, 2, 16)) [this.c] = 123; >[this.c] : Symbol(Inner[this.c], Decl(typeOfThisInStaticMembers12.ts, 3, 30)) +>this : Symbol(Inner, Decl(typeOfThisInStaticMembers12.ts, 2, 16)) } } diff --git a/tests/baselines/reference/typeOfThisInStaticMembers12(target=es6).types b/tests/baselines/reference/typeOfThisInStaticMembers12(target=es6).types index ca37b9e4e200e..539f49702b2b4 100644 --- a/tests/baselines/reference/typeOfThisInStaticMembers12(target=es6).types +++ b/tests/baselines/reference/typeOfThisInStaticMembers12(target=es6).types @@ -14,14 +14,14 @@ class C { static [this.c] = 123; >[this.c] : number >this.c : any ->this : any +>this : typeof Inner >c : any >123 : 123 [this.c] = 123; >[this.c] : number >this.c : any ->this : any +>this : this >c : any >123 : 123 } diff --git a/tests/baselines/reference/typeOfThisInStaticMembers12(target=esnext).errors.txt b/tests/baselines/reference/typeOfThisInStaticMembers12(target=esnext).errors.txt index 3855b2ee7b651..736afd3313057 100644 --- a/tests/baselines/reference/typeOfThisInStaticMembers12(target=esnext).errors.txt +++ b/tests/baselines/reference/typeOfThisInStaticMembers12(target=esnext).errors.txt @@ -1,10 +1,12 @@ tests/cases/conformance/classes/members/instanceAndStaticMembers/typeOfThisInStaticMembers12.ts(4,16): error TS1166: A computed property name in a class property declaration must have a simple literal type or a 'unique symbol' type. tests/cases/conformance/classes/members/instanceAndStaticMembers/typeOfThisInStaticMembers12.ts(4,17): error TS2465: 'this' cannot be referenced in a computed property name. +tests/cases/conformance/classes/members/instanceAndStaticMembers/typeOfThisInStaticMembers12.ts(4,22): error TS2339: Property 'c' does not exist on type 'typeof Inner'. tests/cases/conformance/classes/members/instanceAndStaticMembers/typeOfThisInStaticMembers12.ts(5,9): error TS1166: A computed property name in a class property declaration must have a simple literal type or a 'unique symbol' type. tests/cases/conformance/classes/members/instanceAndStaticMembers/typeOfThisInStaticMembers12.ts(5,10): error TS2465: 'this' cannot be referenced in a computed property name. +tests/cases/conformance/classes/members/instanceAndStaticMembers/typeOfThisInStaticMembers12.ts(5,15): error TS2339: Property 'c' does not exist on type 'Inner'. -==== tests/cases/conformance/classes/members/instanceAndStaticMembers/typeOfThisInStaticMembers12.ts (4 errors) ==== +==== tests/cases/conformance/classes/members/instanceAndStaticMembers/typeOfThisInStaticMembers12.ts (6 errors) ==== class C { static readonly c: "foo" = "foo" static bar = class Inner { @@ -13,11 +15,15 @@ tests/cases/conformance/classes/members/instanceAndStaticMembers/typeOfThisInSta !!! error TS1166: A computed property name in a class property declaration must have a simple literal type or a 'unique symbol' type. ~~~~ !!! error TS2465: 'this' cannot be referenced in a computed property name. + ~ +!!! error TS2339: Property 'c' does not exist on type 'typeof Inner'. [this.c] = 123; ~~~~~~~~ !!! error TS1166: A computed property name in a class property declaration must have a simple literal type or a 'unique symbol' type. ~~~~ !!! error TS2465: 'this' cannot be referenced in a computed property name. + ~ +!!! error TS2339: Property 'c' does not exist on type 'Inner'. } } \ No newline at end of file diff --git a/tests/baselines/reference/typeOfThisInStaticMembers12(target=esnext).symbols b/tests/baselines/reference/typeOfThisInStaticMembers12(target=esnext).symbols index 16ad5c64fd0df..6e778e2c523a8 100644 --- a/tests/baselines/reference/typeOfThisInStaticMembers12(target=esnext).symbols +++ b/tests/baselines/reference/typeOfThisInStaticMembers12(target=esnext).symbols @@ -11,9 +11,11 @@ class C { static [this.c] = 123; >[this.c] : Symbol(Inner[this.c], Decl(typeOfThisInStaticMembers12.ts, 2, 31)) +>this : Symbol(Inner, Decl(typeOfThisInStaticMembers12.ts, 2, 16)) [this.c] = 123; >[this.c] : Symbol(Inner[this.c], Decl(typeOfThisInStaticMembers12.ts, 3, 30)) +>this : Symbol(Inner, Decl(typeOfThisInStaticMembers12.ts, 2, 16)) } } diff --git a/tests/baselines/reference/typeOfThisInStaticMembers12(target=esnext).types b/tests/baselines/reference/typeOfThisInStaticMembers12(target=esnext).types index ca37b9e4e200e..539f49702b2b4 100644 --- a/tests/baselines/reference/typeOfThisInStaticMembers12(target=esnext).types +++ b/tests/baselines/reference/typeOfThisInStaticMembers12(target=esnext).types @@ -14,14 +14,14 @@ class C { static [this.c] = 123; >[this.c] : number >this.c : any ->this : any +>this : typeof Inner >c : any >123 : 123 [this.c] = 123; >[this.c] : number >this.c : any ->this : any +>this : this >c : any >123 : 123 } diff --git a/tests/baselines/reference/typeOfThisInStaticMembers13(target=es2022).errors.txt b/tests/baselines/reference/typeOfThisInStaticMembers13(target=es2022).errors.txt index 804765ba1290d..e1addc1ad1f6d 100644 --- a/tests/baselines/reference/typeOfThisInStaticMembers13(target=es2022).errors.txt +++ b/tests/baselines/reference/typeOfThisInStaticMembers13(target=es2022).errors.txt @@ -1,10 +1,12 @@ tests/cases/conformance/classes/members/instanceAndStaticMembers/typeOfThisInStaticMembers13.ts(4,16): error TS1166: A computed property name in a class property declaration must have a simple literal type or a 'unique symbol' type. tests/cases/conformance/classes/members/instanceAndStaticMembers/typeOfThisInStaticMembers13.ts(4,17): error TS2465: 'this' cannot be referenced in a computed property name. +tests/cases/conformance/classes/members/instanceAndStaticMembers/typeOfThisInStaticMembers13.ts(4,22): error TS2339: Property 'c' does not exist on type 'typeof Inner'. tests/cases/conformance/classes/members/instanceAndStaticMembers/typeOfThisInStaticMembers13.ts(5,9): error TS1166: A computed property name in a class property declaration must have a simple literal type or a 'unique symbol' type. tests/cases/conformance/classes/members/instanceAndStaticMembers/typeOfThisInStaticMembers13.ts(5,10): error TS2465: 'this' cannot be referenced in a computed property name. +tests/cases/conformance/classes/members/instanceAndStaticMembers/typeOfThisInStaticMembers13.ts(5,15): error TS2339: Property 'c' does not exist on type 'Inner'. -==== tests/cases/conformance/classes/members/instanceAndStaticMembers/typeOfThisInStaticMembers13.ts (4 errors) ==== +==== tests/cases/conformance/classes/members/instanceAndStaticMembers/typeOfThisInStaticMembers13.ts (6 errors) ==== class C { static readonly c: "foo" = "foo" static bar = class Inner { @@ -13,11 +15,15 @@ tests/cases/conformance/classes/members/instanceAndStaticMembers/typeOfThisInSta !!! error TS1166: A computed property name in a class property declaration must have a simple literal type or a 'unique symbol' type. ~~~~ !!! error TS2465: 'this' cannot be referenced in a computed property name. + ~ +!!! error TS2339: Property 'c' does not exist on type 'typeof Inner'. [this.c] = 123; ~~~~~~~~ !!! error TS1166: A computed property name in a class property declaration must have a simple literal type or a 'unique symbol' type. ~~~~ !!! error TS2465: 'this' cannot be referenced in a computed property name. + ~ +!!! error TS2339: Property 'c' does not exist on type 'Inner'. } } \ No newline at end of file diff --git a/tests/baselines/reference/typeOfThisInStaticMembers13(target=es2022).symbols b/tests/baselines/reference/typeOfThisInStaticMembers13(target=es2022).symbols index 806a34350b5b9..eb07aed6995f4 100644 --- a/tests/baselines/reference/typeOfThisInStaticMembers13(target=es2022).symbols +++ b/tests/baselines/reference/typeOfThisInStaticMembers13(target=es2022).symbols @@ -11,9 +11,11 @@ class C { static [this.c] = 123; >[this.c] : Symbol(Inner[this.c], Decl(typeOfThisInStaticMembers13.ts, 2, 31)) +>this : Symbol(Inner, Decl(typeOfThisInStaticMembers13.ts, 2, 16)) [this.c] = 123; >[this.c] : Symbol(Inner[this.c], Decl(typeOfThisInStaticMembers13.ts, 3, 30)) +>this : Symbol(Inner, Decl(typeOfThisInStaticMembers13.ts, 2, 16)) } } diff --git a/tests/baselines/reference/typeOfThisInStaticMembers13(target=es2022).types b/tests/baselines/reference/typeOfThisInStaticMembers13(target=es2022).types index bb274c6f556e7..1c111faf79df8 100644 --- a/tests/baselines/reference/typeOfThisInStaticMembers13(target=es2022).types +++ b/tests/baselines/reference/typeOfThisInStaticMembers13(target=es2022).types @@ -14,14 +14,14 @@ class C { static [this.c] = 123; >[this.c] : number >this.c : any ->this : any +>this : typeof Inner >c : any >123 : 123 [this.c] = 123; >[this.c] : number >this.c : any ->this : any +>this : this >c : any >123 : 123 } diff --git a/tests/baselines/reference/typeOfThisInStaticMembers13(target=es5).errors.txt b/tests/baselines/reference/typeOfThisInStaticMembers13(target=es5).errors.txt index 804765ba1290d..e1addc1ad1f6d 100644 --- a/tests/baselines/reference/typeOfThisInStaticMembers13(target=es5).errors.txt +++ b/tests/baselines/reference/typeOfThisInStaticMembers13(target=es5).errors.txt @@ -1,10 +1,12 @@ tests/cases/conformance/classes/members/instanceAndStaticMembers/typeOfThisInStaticMembers13.ts(4,16): error TS1166: A computed property name in a class property declaration must have a simple literal type or a 'unique symbol' type. tests/cases/conformance/classes/members/instanceAndStaticMembers/typeOfThisInStaticMembers13.ts(4,17): error TS2465: 'this' cannot be referenced in a computed property name. +tests/cases/conformance/classes/members/instanceAndStaticMembers/typeOfThisInStaticMembers13.ts(4,22): error TS2339: Property 'c' does not exist on type 'typeof Inner'. tests/cases/conformance/classes/members/instanceAndStaticMembers/typeOfThisInStaticMembers13.ts(5,9): error TS1166: A computed property name in a class property declaration must have a simple literal type or a 'unique symbol' type. tests/cases/conformance/classes/members/instanceAndStaticMembers/typeOfThisInStaticMembers13.ts(5,10): error TS2465: 'this' cannot be referenced in a computed property name. +tests/cases/conformance/classes/members/instanceAndStaticMembers/typeOfThisInStaticMembers13.ts(5,15): error TS2339: Property 'c' does not exist on type 'Inner'. -==== tests/cases/conformance/classes/members/instanceAndStaticMembers/typeOfThisInStaticMembers13.ts (4 errors) ==== +==== tests/cases/conformance/classes/members/instanceAndStaticMembers/typeOfThisInStaticMembers13.ts (6 errors) ==== class C { static readonly c: "foo" = "foo" static bar = class Inner { @@ -13,11 +15,15 @@ tests/cases/conformance/classes/members/instanceAndStaticMembers/typeOfThisInSta !!! error TS1166: A computed property name in a class property declaration must have a simple literal type or a 'unique symbol' type. ~~~~ !!! error TS2465: 'this' cannot be referenced in a computed property name. + ~ +!!! error TS2339: Property 'c' does not exist on type 'typeof Inner'. [this.c] = 123; ~~~~~~~~ !!! error TS1166: A computed property name in a class property declaration must have a simple literal type or a 'unique symbol' type. ~~~~ !!! error TS2465: 'this' cannot be referenced in a computed property name. + ~ +!!! error TS2339: Property 'c' does not exist on type 'Inner'. } } \ No newline at end of file diff --git a/tests/baselines/reference/typeOfThisInStaticMembers13(target=es5).symbols b/tests/baselines/reference/typeOfThisInStaticMembers13(target=es5).symbols index 806a34350b5b9..eb07aed6995f4 100644 --- a/tests/baselines/reference/typeOfThisInStaticMembers13(target=es5).symbols +++ b/tests/baselines/reference/typeOfThisInStaticMembers13(target=es5).symbols @@ -11,9 +11,11 @@ class C { static [this.c] = 123; >[this.c] : Symbol(Inner[this.c], Decl(typeOfThisInStaticMembers13.ts, 2, 31)) +>this : Symbol(Inner, Decl(typeOfThisInStaticMembers13.ts, 2, 16)) [this.c] = 123; >[this.c] : Symbol(Inner[this.c], Decl(typeOfThisInStaticMembers13.ts, 3, 30)) +>this : Symbol(Inner, Decl(typeOfThisInStaticMembers13.ts, 2, 16)) } } diff --git a/tests/baselines/reference/typeOfThisInStaticMembers13(target=es5).types b/tests/baselines/reference/typeOfThisInStaticMembers13(target=es5).types index bb274c6f556e7..1c111faf79df8 100644 --- a/tests/baselines/reference/typeOfThisInStaticMembers13(target=es5).types +++ b/tests/baselines/reference/typeOfThisInStaticMembers13(target=es5).types @@ -14,14 +14,14 @@ class C { static [this.c] = 123; >[this.c] : number >this.c : any ->this : any +>this : typeof Inner >c : any >123 : 123 [this.c] = 123; >[this.c] : number >this.c : any ->this : any +>this : this >c : any >123 : 123 } diff --git a/tests/baselines/reference/typeOfThisInStaticMembers13(target=es6).errors.txt b/tests/baselines/reference/typeOfThisInStaticMembers13(target=es6).errors.txt index 804765ba1290d..e1addc1ad1f6d 100644 --- a/tests/baselines/reference/typeOfThisInStaticMembers13(target=es6).errors.txt +++ b/tests/baselines/reference/typeOfThisInStaticMembers13(target=es6).errors.txt @@ -1,10 +1,12 @@ tests/cases/conformance/classes/members/instanceAndStaticMembers/typeOfThisInStaticMembers13.ts(4,16): error TS1166: A computed property name in a class property declaration must have a simple literal type or a 'unique symbol' type. tests/cases/conformance/classes/members/instanceAndStaticMembers/typeOfThisInStaticMembers13.ts(4,17): error TS2465: 'this' cannot be referenced in a computed property name. +tests/cases/conformance/classes/members/instanceAndStaticMembers/typeOfThisInStaticMembers13.ts(4,22): error TS2339: Property 'c' does not exist on type 'typeof Inner'. tests/cases/conformance/classes/members/instanceAndStaticMembers/typeOfThisInStaticMembers13.ts(5,9): error TS1166: A computed property name in a class property declaration must have a simple literal type or a 'unique symbol' type. tests/cases/conformance/classes/members/instanceAndStaticMembers/typeOfThisInStaticMembers13.ts(5,10): error TS2465: 'this' cannot be referenced in a computed property name. +tests/cases/conformance/classes/members/instanceAndStaticMembers/typeOfThisInStaticMembers13.ts(5,15): error TS2339: Property 'c' does not exist on type 'Inner'. -==== tests/cases/conformance/classes/members/instanceAndStaticMembers/typeOfThisInStaticMembers13.ts (4 errors) ==== +==== tests/cases/conformance/classes/members/instanceAndStaticMembers/typeOfThisInStaticMembers13.ts (6 errors) ==== class C { static readonly c: "foo" = "foo" static bar = class Inner { @@ -13,11 +15,15 @@ tests/cases/conformance/classes/members/instanceAndStaticMembers/typeOfThisInSta !!! error TS1166: A computed property name in a class property declaration must have a simple literal type or a 'unique symbol' type. ~~~~ !!! error TS2465: 'this' cannot be referenced in a computed property name. + ~ +!!! error TS2339: Property 'c' does not exist on type 'typeof Inner'. [this.c] = 123; ~~~~~~~~ !!! error TS1166: A computed property name in a class property declaration must have a simple literal type or a 'unique symbol' type. ~~~~ !!! error TS2465: 'this' cannot be referenced in a computed property name. + ~ +!!! error TS2339: Property 'c' does not exist on type 'Inner'. } } \ No newline at end of file diff --git a/tests/baselines/reference/typeOfThisInStaticMembers13(target=es6).symbols b/tests/baselines/reference/typeOfThisInStaticMembers13(target=es6).symbols index 806a34350b5b9..eb07aed6995f4 100644 --- a/tests/baselines/reference/typeOfThisInStaticMembers13(target=es6).symbols +++ b/tests/baselines/reference/typeOfThisInStaticMembers13(target=es6).symbols @@ -11,9 +11,11 @@ class C { static [this.c] = 123; >[this.c] : Symbol(Inner[this.c], Decl(typeOfThisInStaticMembers13.ts, 2, 31)) +>this : Symbol(Inner, Decl(typeOfThisInStaticMembers13.ts, 2, 16)) [this.c] = 123; >[this.c] : Symbol(Inner[this.c], Decl(typeOfThisInStaticMembers13.ts, 3, 30)) +>this : Symbol(Inner, Decl(typeOfThisInStaticMembers13.ts, 2, 16)) } } diff --git a/tests/baselines/reference/typeOfThisInStaticMembers13(target=es6).types b/tests/baselines/reference/typeOfThisInStaticMembers13(target=es6).types index bb274c6f556e7..1c111faf79df8 100644 --- a/tests/baselines/reference/typeOfThisInStaticMembers13(target=es6).types +++ b/tests/baselines/reference/typeOfThisInStaticMembers13(target=es6).types @@ -14,14 +14,14 @@ class C { static [this.c] = 123; >[this.c] : number >this.c : any ->this : any +>this : typeof Inner >c : any >123 : 123 [this.c] = 123; >[this.c] : number >this.c : any ->this : any +>this : this >c : any >123 : 123 } diff --git a/tests/baselines/reference/typeOfThisInStaticMembers13(target=esnext).errors.txt b/tests/baselines/reference/typeOfThisInStaticMembers13(target=esnext).errors.txt index 804765ba1290d..e1addc1ad1f6d 100644 --- a/tests/baselines/reference/typeOfThisInStaticMembers13(target=esnext).errors.txt +++ b/tests/baselines/reference/typeOfThisInStaticMembers13(target=esnext).errors.txt @@ -1,10 +1,12 @@ tests/cases/conformance/classes/members/instanceAndStaticMembers/typeOfThisInStaticMembers13.ts(4,16): error TS1166: A computed property name in a class property declaration must have a simple literal type or a 'unique symbol' type. tests/cases/conformance/classes/members/instanceAndStaticMembers/typeOfThisInStaticMembers13.ts(4,17): error TS2465: 'this' cannot be referenced in a computed property name. +tests/cases/conformance/classes/members/instanceAndStaticMembers/typeOfThisInStaticMembers13.ts(4,22): error TS2339: Property 'c' does not exist on type 'typeof Inner'. tests/cases/conformance/classes/members/instanceAndStaticMembers/typeOfThisInStaticMembers13.ts(5,9): error TS1166: A computed property name in a class property declaration must have a simple literal type or a 'unique symbol' type. tests/cases/conformance/classes/members/instanceAndStaticMembers/typeOfThisInStaticMembers13.ts(5,10): error TS2465: 'this' cannot be referenced in a computed property name. +tests/cases/conformance/classes/members/instanceAndStaticMembers/typeOfThisInStaticMembers13.ts(5,15): error TS2339: Property 'c' does not exist on type 'Inner'. -==== tests/cases/conformance/classes/members/instanceAndStaticMembers/typeOfThisInStaticMembers13.ts (4 errors) ==== +==== tests/cases/conformance/classes/members/instanceAndStaticMembers/typeOfThisInStaticMembers13.ts (6 errors) ==== class C { static readonly c: "foo" = "foo" static bar = class Inner { @@ -13,11 +15,15 @@ tests/cases/conformance/classes/members/instanceAndStaticMembers/typeOfThisInSta !!! error TS1166: A computed property name in a class property declaration must have a simple literal type or a 'unique symbol' type. ~~~~ !!! error TS2465: 'this' cannot be referenced in a computed property name. + ~ +!!! error TS2339: Property 'c' does not exist on type 'typeof Inner'. [this.c] = 123; ~~~~~~~~ !!! error TS1166: A computed property name in a class property declaration must have a simple literal type or a 'unique symbol' type. ~~~~ !!! error TS2465: 'this' cannot be referenced in a computed property name. + ~ +!!! error TS2339: Property 'c' does not exist on type 'Inner'. } } \ No newline at end of file diff --git a/tests/baselines/reference/typeOfThisInStaticMembers13(target=esnext).symbols b/tests/baselines/reference/typeOfThisInStaticMembers13(target=esnext).symbols index 806a34350b5b9..eb07aed6995f4 100644 --- a/tests/baselines/reference/typeOfThisInStaticMembers13(target=esnext).symbols +++ b/tests/baselines/reference/typeOfThisInStaticMembers13(target=esnext).symbols @@ -11,9 +11,11 @@ class C { static [this.c] = 123; >[this.c] : Symbol(Inner[this.c], Decl(typeOfThisInStaticMembers13.ts, 2, 31)) +>this : Symbol(Inner, Decl(typeOfThisInStaticMembers13.ts, 2, 16)) [this.c] = 123; >[this.c] : Symbol(Inner[this.c], Decl(typeOfThisInStaticMembers13.ts, 3, 30)) +>this : Symbol(Inner, Decl(typeOfThisInStaticMembers13.ts, 2, 16)) } } diff --git a/tests/baselines/reference/typeOfThisInStaticMembers13(target=esnext).types b/tests/baselines/reference/typeOfThisInStaticMembers13(target=esnext).types index bb274c6f556e7..1c111faf79df8 100644 --- a/tests/baselines/reference/typeOfThisInStaticMembers13(target=esnext).types +++ b/tests/baselines/reference/typeOfThisInStaticMembers13(target=esnext).types @@ -14,14 +14,14 @@ class C { static [this.c] = 123; >[this.c] : number >this.c : any ->this : any +>this : typeof Inner >c : any >123 : 123 [this.c] = 123; >[this.c] : number >this.c : any ->this : any +>this : this >c : any >123 : 123 }