diff --git a/src/compiler/ast.ts b/src/compiler/ast.ts index 824bbc46a22..d1f54d55340 100644 --- a/src/compiler/ast.ts +++ b/src/compiler/ast.ts @@ -118,14 +118,13 @@ import { getTransformFlagsSubtreeExclusions, HasChildren, HasDecorators, + HasExpression, HasJSDoc, HasLocals, HasModifiers, HasName, - hasProperty, HeritageClause, Identifier, - idText, IfStatement, ImportAttribute, ImportAttributeName, @@ -143,7 +142,9 @@ import { InKeyword, InterfaceDeclaration, IntersectionTypeNode, - isAstParenthesizedExpression, + astIsElementAccessExpression, + astIsParenthesizedExpression, + astIsPropertyAccessExpression, IScriptSnapshot, isLogicalOrCoalescingAssignmentOperator, isParseTreeNode, @@ -291,7 +292,6 @@ import { OptionalChainRoot, OptionalTypeNode, OuterExpression, - OuterExpressionKinds, OutKeyword, OverrideKeyword, PackageJsonInfo, @@ -402,9 +402,59 @@ import { VoidExpression, WhileStatement, WithStatement, - YieldExpression + YieldExpression, + HasFlowNode, + BindableStaticNameExpression, + BindableObjectDefinePropertyCall, + BindableStaticAccessExpression, + BindableStaticElementAccessExpression, + LiteralLikeElementAccessExpression, + AccessExpression, + WrappedExpression, + AssignmentExpression, + AssignmentOperatorToken, + BindableStaticPropertyAssignmentExpression, + BindablePropertyAssignmentExpression, + ThisContainer, + DynamicNamedDeclaration, + DynamicNamedBinaryExpression, + VariableLikeDeclaration, + HasInitializer, + AutoAccessorPropertyDeclaration, + PrologueDirective, + HasText, + AmbientModuleDeclaration, + NonGlobalAmbientModuleDeclaration, + HasSymbol, + HasType, + HasTypeParameters, + HasParameters, + HasBody, + HasQuestionToken, + HasEndFlowNode, + HasTypeArguments, + InternalHasTypeArguments, + HasElements, + HasMembers, + HasStatement, + HasExclamationToken, + HasAsteriskToken, + HasQuestionDotToken, + HasComment, + HasStatements, + astIdText, + HasTypes, + HasTagName, + HasIsTypeOnly, + InternalHasModifiers, } from "./_namespaces/ts.js"; +const cloneNodeMap: Partial AstNode>> = {}; +const createDataInstanceMap: Partial AstData>> = {}; +const copyDataPropertiesMap: Partial void>> = {}; +const shadowNodeMap: Partial AstNode>> = {}; +const shadowDataMap: Partial AstData>> = {}; + // dprint-ignore class AstNodeArrayExtraFields { /** @internal */ nodes: NodeArray | undefined = undefined; @@ -513,14 +563,14 @@ class AstNodeExtraFields { /** @internal */ __end: number = -1; } -let astNodeCloneCore: (node: AstNode) => AstNode; -let astNodeShadowCore: (node: AstNode) => AstNode; +let cloneNodeCore: (node: AstNode) => AstNode; +let shadowCore: (node: AstNode) => AstNode; // dprint-ignore export class AstNode = Node> { static { - astNodeCloneCore = node => node.cloneCore(); - astNodeShadowCore = node => node.shadowCore(); + cloneNodeCore = node => node.cloneCore(); + shadowCore = node => node.shadowCore(); } private _node: N | undefined = undefined; @@ -530,7 +580,7 @@ export class AstNode = Node> | undefined = undefined; // Parent node (initialized by binding) + parent: AstNodeOneOf = undefined!; // Parent node (initialized by binding) flags: NodeFlags = NodeFlags.None; pos = -1; end = -1; @@ -608,7 +658,7 @@ export class AstNode = Node = Node = Node = Node = Node; +/** @internal */ +export type AstHasEndFlowNode = AstNodeOneOf; /** @internal */ export type AstHasLocals = AstNodeOneOf; export type AstHasDecorators = AstNodeOneOf; export type AstHasModifiers = AstNodeOneOf; /** @internal */ +export type AstInternalHasModifiers = AstNodeOneOf; +/** @internal */ export type AstHasChildren = AstNodeOneOf; /** @internal */ +export type AstHasSymbol = AstNodeOneOf; +/** @internal */ +export type AstHasType = AstNodeOneOf; +/** @internal */ +export type AstHasTypes = AstNodeOneOf; +/** @internal */ +export type AstHasTypeParameters = AstNodeOneOf; +/** @internal */ +export type AstHasTypeArguments = AstNodeOneOf; +/** @internal */ +export type AstInternalHasTypeArguments = AstNodeOneOf; +/** @internal */ +export type AstHasParameters = AstNodeOneOf; +/** @internal */ +export type AstHasBody = AstNodeOneOf; +/** @internal */ +export type AstHasQuestionToken = AstNodeOneOf; +/** @internal */ +export type AstHasElements = AstNodeOneOf; +/** @internal */ +export type AstHasMembers = AstNodeOneOf; +/** @internal */ +export type AstHasStatement = AstNodeOneOf; +/** @internal */ +export type AstHasStatements = AstNodeOneOf; +/** @internal */ +export type AstHasExclamationToken = AstNodeOneOf; +/** @internal */ +export type AstHasAsteriskToken = AstNodeOneOf; +/** @internal */ +export type AstHasQuestionDotToken = AstNodeOneOf; +/** @internal */ +export type AstHasIsTypeOnly = AstNodeOneOf; +/** @internal */ +export type AstHasTagName = AstNodeOneOf; +/** @internal */ +export type AstHasComment = AstNodeOneOf; +/** @internal */ export type AstForEachChildNodes = AstNodeOneOf; export type AstDeclaration = AstNode; export type AstTypeNode = AstNode>; @@ -1490,6 +1528,10 @@ export type AstEndOfFileToken = AstNode; // dprint-ignore export class AstEndOfFileTokenData extends AstTokenData { /** @internal */ jsDoc: JSDocArray | undefined = undefined; // initialized by parser (JSDocContainer) + + static { + createDataInstanceMap[SyntaxKind.EndOfFileToken] = _ => new this(); + } } export type AstThisExpression = AstNode; @@ -1497,6 +1539,10 @@ export type AstThisExpression = AstNode; // dprint-ignore export class AstThisExpressionData extends AstTokenData { /** @internal */ flowNode: FlowNode | undefined = undefined; // initialized by checker (FlowContainer) + + static { + createDataInstanceMap[SyntaxKind.ThisKeyword] = _ => new this(); + } } export type AstSuperExpression = AstNode; @@ -1504,6 +1550,10 @@ export type AstSuperExpression = AstNode; // dprint-ignore export class AstSuperExpressionData extends AstTokenData { /** @internal */ flowNode: FlowNode | undefined = undefined; // initialized by checker (FlowContainer) + + static { + createDataInstanceMap[SyntaxKind.SuperKeyword] = _ => new this(); + } } export type AstImportExpression = AstNode; @@ -1581,6 +1631,20 @@ export class AstIdentifierData extends AstTokenData { } return transformFlags; } + + static { + createDataInstanceMap[SyntaxKind.Identifier] = _ => new AstIdentifierData(); + copyDataPropertiesMap[SyntaxKind.Identifier] = (data, clone) => { + Debug.assert(data instanceof this); + Debug.assert(clone instanceof this); + clone.escapedText = data.escapedText; + clone.resolvedSymbol = data.resolvedSymbol; + clone.jsDoc = data.jsDoc; + clone.symbol = data.symbol; + clone.localSymbol = data.localSymbol; + clone.flowNode = data.flowNode; + } + } } export type AstQualifiedName = AstNode; @@ -1596,6 +1660,10 @@ export class AstQualifiedNameData extends AstData { return propagateChildFlags(this.left) | propagateIdentifierNameFlags(this.right); } + + static { + createDataInstanceMap[SyntaxKind.QualifiedName] = _ => new this(); + } } export type AstEntityName = AstNodeOneOf; @@ -1614,6 +1682,10 @@ export class AstComputedPropertyNameData extends AstData { TransformFlags.ContainsES2015 | TransformFlags.ContainsComputedPropertyName; } + + static { + createDataInstanceMap[SyntaxKind.ComputedPropertyName] = _ => new this(); + } } export type AstPrivateIdentifier = AstNode; @@ -1625,6 +1697,10 @@ export class AstPrivateIdentifierData extends AstTokenData { /** @internal */ override computeTransformFlags(_: AstNode): TransformFlags { return TransformFlags.ContainsClassFields; } + + static { + createDataInstanceMap[SyntaxKind.PrivateIdentifier] = _ => new this(); + } } export type AstTypeParameterDeclaration = AstNode; @@ -1640,6 +1716,11 @@ export class AstTypeParameterDeclarationData extends AstTypeScriptNodeData { /** @internal */ jsDoc: JSDocArray | undefined = undefined; // initialized by parser (JSDocContainer) /** @internal */ symbol: Symbol = undefined!; // initialized by binder (Declaration) /** @internal */ localSymbol: Symbol | undefined = undefined; // initialized by binder (Declaration) + + + static { + createDataInstanceMap[SyntaxKind.TypeParameter] = _ => new this(); + } } export type AstParameterDeclaration = AstNode; @@ -1672,6 +1753,11 @@ export class AstParameterDeclarationData extends AstData { (this.dotDotDotToken ?? this.initializer ? TransformFlags.ContainsES2015 : TransformFlags.None) | (modifiersToFlags(this.modifiers?.items) & ModifierFlags.ParameterPropertyModifier ? TransformFlags.ContainsTypeScriptClassSyntax : TransformFlags.None); } + + + static { + createDataInstanceMap[SyntaxKind.Parameter] = _ => new this(); + } } export type AstDecorator = AstNode; @@ -1686,6 +1772,10 @@ export class AstDecoratorData extends AstData { TransformFlags.ContainsTypeScriptClassSyntax | TransformFlags.ContainsDecorators; } + + static { + createDataInstanceMap[SyntaxKind.Decorator] = _ => new this(); + } } export type AstPropertySignature = AstNode; @@ -1701,6 +1791,11 @@ export class AstPropertySignatureData extends AstTypeScriptNodeData { /** @internal */ symbol: Symbol = undefined!; // initialized by binder (Declaration) /** @internal */ localSymbol: Symbol | undefined = undefined; // initialized by binder (Declaration) /** @internal */ jsDoc: JSDocArray | undefined = undefined; // initialized by parser (JSDocContainer) + + + static { + createDataInstanceMap[SyntaxKind.PropertySignature] = _ => new this(); + } } export type AstSignatureDeclaration = AstNodeOneOf; @@ -1718,6 +1813,11 @@ export class AstCallSignatureDeclarationData extends AstTypeScriptNodeData { /** @internal */ symbol: Symbol = undefined!; // initialized by binder (Declaration) /** @internal */ localSymbol: Symbol | undefined = undefined; // initialized by binder (Declaration) /** @internal */ jsDoc: JSDocArray | undefined = undefined; // initialized by parser (JSDocContainer) + + + static { + createDataInstanceMap[SyntaxKind.CallSignature] = _ => new this(); + } } export type AstConstructSignatureDeclaration = AstNode; @@ -1734,6 +1834,11 @@ export class AstConstructSignatureDeclarationData extends AstTypeScriptNodeData /** @internal */ localSymbol: Symbol | undefined = undefined; // initialized by binder (Declaration) /** @internal */ locals: SymbolTable | undefined = undefined; /** @internal */ nextContainer: AstHasLocals | undefined = undefined; + + + static { + createDataInstanceMap[SyntaxKind.ConstructSignature] = _ => new this(); + } } export type AstVariableDeclaration = AstNode; @@ -1754,8 +1859,15 @@ export class AstVariableDeclarationData extends AstData { propagateChildFlags(this.initializer) | (this.exclamationToken ?? this.type ? TransformFlags.ContainsTypeScript : TransformFlags.None); } + + + static { + createDataInstanceMap[SyntaxKind.VariableDeclaration] = _ => new this(); + } } +export type AstVariableLikeDeclaration = AstNodeOneOf; + export type AstVariableDeclarationList = AstNode; // dprint-ignore @@ -1774,6 +1886,11 @@ export class AstVariableDeclarationListData extends AstData { } return transformFlags; } + + + static { + createDataInstanceMap[SyntaxKind.VariableDeclarationList] = _ => new this(); + } } export type AstBindingElement = AstNode; @@ -1797,9 +1914,14 @@ export class AstBindingElementData extends AstData { (this.dotDotDotToken ? TransformFlags.ContainsRestOrSpread : TransformFlags.None) | TransformFlags.ContainsES2015; } + + static { + createDataInstanceMap[SyntaxKind.BindingElement] = _ => new this(); + } } export type AstPropertyDeclaration = AstNode; +export type AstAutoAccessorPropertyDeclaration = AstNode; // dprint-ignore export class AstPropertyDeclarationData extends AstData { @@ -1825,6 +1947,10 @@ export class AstPropertyDeclarationData extends AstData { (this.name.kind === SyntaxKind.ComputedPropertyName || modifierFlags & ModifierFlags.Static && this.initializer ? TransformFlags.ContainsTypeScriptClassSyntax : TransformFlags.None) | TransformFlags.ContainsClassFields; } + + static { + createDataInstanceMap[SyntaxKind.PropertyDeclaration] = _ => new this(); + } } export type AstPropertyAssignment = AstNode; @@ -1845,6 +1971,10 @@ export class AstPropertyAssignmentData extends AstData { return propagateNameFlags(this.name) | propagateChildFlags(this.initializer); } + + static { + createDataInstanceMap[SyntaxKind.PropertyAssignment] = _ => new this(); + } } export type AstShorthandPropertyAssignment = AstNode; @@ -1869,6 +1999,10 @@ export class AstShorthandPropertyAssignmentData extends AstData { propagateChildFlags(this.objectAssignmentInitializer) | TransformFlags.ContainsES2015; } + + static { + createDataInstanceMap[SyntaxKind.ShorthandPropertyAssignment] = _ => new this(); + } } export type AstSpreadAssignment = AstNode; @@ -1886,6 +2020,10 @@ export class AstSpreadAssignmentData extends AstData { TransformFlags.ContainsES2018 | TransformFlags.ContainsObjectRestOrSpread; } + + static { + createDataInstanceMap[SyntaxKind.SpreadAssignment] = _ => new this(); + } } export type AstBindingPattern = AstNodeOneOf; @@ -1904,6 +2042,10 @@ export class AstObjectBindingPatternData extends AstData { } return transformFlags; } + + static { + createDataInstanceMap[SyntaxKind.ObjectBindingPattern] = _ => new this(); + } } export type AstArrayBindingElement = AstNodeOneOf; @@ -1918,6 +2060,10 @@ export class AstArrayBindingPatternData extends AstData { TransformFlags.ContainsES2015 | TransformFlags.ContainsBindingPattern; } + + static { + createDataInstanceMap[SyntaxKind.ArrayBindingPattern] = _ => new this(); + } } export type AstFunctionDeclaration = AstNode; @@ -1965,6 +2111,10 @@ export class AstFunctionDeclarationData extends AstData { TransformFlags.ContainsHoistedDeclarationOrCompletion; } } + + static { + createDataInstanceMap[SyntaxKind.FunctionDeclaration] = _ => new this(); + } } // dprint-ignore @@ -1982,6 +2132,10 @@ export class AstMethodSignatureData extends AstTypeScriptNodeData { /** @internal */ localSymbol: Symbol | undefined = undefined; // initialized by binder (Declaration) /** @internal */ locals: SymbolTable | undefined = undefined; /** @internal */ nextContainer: AstHasLocals | undefined = undefined; + + static { + createDataInstanceMap[SyntaxKind.MethodSignature] = _ => new this(); + } } // dprint-ignore @@ -2031,6 +2185,10 @@ export class AstMethodDeclarationData extends AstData { TransformFlags.ContainsES2015; } } + + static { + createDataInstanceMap[SyntaxKind.MethodDeclaration] = _ => new this(); + } } // dprint-ignore @@ -2061,6 +2219,10 @@ export class AstConstructorDeclarationData extends AstData { TransformFlags.ContainsES2015; } } + + static { + createDataInstanceMap[SyntaxKind.Constructor] = _ => new this(); + } } // dprint-ignore @@ -2070,6 +2232,10 @@ export class AstSemicolonClassElementData extends AstData { /** @internal */ override computeTransformFlags(_: AstNode): TransformFlags { return TransformFlags.None; } + + static { + createDataInstanceMap[SyntaxKind.SemicolonClassElement] = _ => new this(); + } } // dprint-ignore @@ -2104,6 +2270,10 @@ export class AstGetAccessorDeclarationData extends AstData { (this.type ? TransformFlags.ContainsTypeScript : TransformFlags.None); } } + + static { + createDataInstanceMap[SyntaxKind.GetAccessor] = _ => new this(); + } } // dprint-ignore @@ -2137,6 +2307,10 @@ export class AstSetAccessorDeclarationData extends AstData { (this.type ? TransformFlags.ContainsTypeScript : TransformFlags.None); } } + + static { + createDataInstanceMap[SyntaxKind.SetAccessor] = _ => new this(); + } } export type AstAccessorDeclaration = AstNodeOneOf; @@ -2154,6 +2328,10 @@ export class AstIndexSignatureDeclarationData extends AstTypeScriptNodeData { /** @internal */ localSymbol: Symbol | undefined = undefined; // initialized by binder (Declaration) /** @internal */ locals: SymbolTable | undefined = undefined; /** @internal */ nextContainer: AstHasLocals | undefined = undefined; + + static { + createDataInstanceMap[SyntaxKind.IndexSignature] = _ => new this(); + } } // dprint-ignore @@ -2172,6 +2350,10 @@ export class AstClassStaticBlockDeclarationData extends AstData { /** @internal */ override computeTransformFlags(_: AstNode): TransformFlags { return propagateChildFlags(this.body) | TransformFlags.ContainsClassFields; } + + static { + createDataInstanceMap[SyntaxKind.ClassStaticBlockDeclaration] = _ => new this(); + } } /** @@ -2185,6 +2367,10 @@ export type AstImportTypeAssertionContainer = AstNode new this(); + } } // dprint-ignore @@ -2195,12 +2381,20 @@ export class AstImportTypeNodeData extends AstTypeScriptNodeData { attributes: AstImportAttributes | undefined = undefined; qualifier: AstEntityName | undefined = undefined; typeArguments: AstNodeArray | undefined = undefined; + + static { + createDataInstanceMap[SyntaxKind.ImportType] = _ => new this(); + } } export type AstKeywordTypeNode = AstNode>; // dprint-ignore export class AstThisTypeNodeData extends AstTypeScriptNodeData { + + static { + createDataInstanceMap[SyntaxKind.ThisType] = _ => new this(); + } } export type AstFunctionOrConstructorTypeNode = AstNodeOneOf; @@ -2218,6 +2412,10 @@ export class AstFunctionTypeNodeData extends AstTypeScriptNodeData { /** @internal */ localSymbol: Symbol | undefined = undefined; // initialized by binder (Declaration) /** @internal */ locals: SymbolTable | undefined = undefined; /** @internal */ nextContainer: AstHasLocals | undefined = undefined; + + static { + createDataInstanceMap[SyntaxKind.FunctionType] = _ => new this(); + } } // dprint-ignore @@ -2233,12 +2431,20 @@ export class AstConstructorTypeNodeData extends AstTypeScriptNodeData { /** @internal */ localSymbol: Symbol | undefined = undefined; // initialized by binder (Declaration) /** @internal */ locals: SymbolTable | undefined = undefined; /** @internal */ nextContainer: AstHasLocals | undefined = undefined; + + static { + createDataInstanceMap[SyntaxKind.ConstructorType] = _ => new this(); + } } // dprint-ignore export class AstTypeReferenceNodeData extends AstTypeScriptNodeData { typeName: AstEntityName = undefined!; typeArguments: AstNodeArray | undefined = undefined; + + static { + createDataInstanceMap[SyntaxKind.TypeReference] = _ => new this(); + } } // dprint-ignore @@ -2246,12 +2452,20 @@ export class AstTypePredicateNodeData extends AstTypeScriptNodeData { assertsModifier: AstAssertsKeyword | undefined = undefined; parameterName: AstIdentifier | AstThisTypeNode = undefined!; type: AstTypeNode | undefined = undefined; + + static { + createDataInstanceMap[SyntaxKind.TypePredicate] = _ => new this(); + } } // dprint-ignore export class AstTypeQueryNodeData extends AstTypeScriptNodeData { exprName: AstEntityName = undefined!; typeArguments: AstNodeArray | undefined = undefined; + + static { + createDataInstanceMap[SyntaxKind.TypeQuery] = _ => new this(); + } } // dprint-ignore @@ -2260,16 +2474,28 @@ export class AstTypeLiteralNodeData extends AstTypeScriptNodeData { /** @internal */ symbol: Symbol = undefined!; // initialized by binder (Declaration) /** @internal */ localSymbol: Symbol | undefined = undefined; // initialized by binder (Declaration) + + static { + createDataInstanceMap[SyntaxKind.TypeLiteral] = _ => new this(); + } } // dprint-ignore export class AstArrayTypeNodeData extends AstTypeScriptNodeData { elementType: AstTypeNode = undefined!; + + static { + createDataInstanceMap[SyntaxKind.ArrayType] = _ => new this(); + } } // dprint-ignore export class AstTupleTypeNodeData extends AstTypeScriptNodeData { elements: AstNodeArray = undefined!; + + static { + createDataInstanceMap[SyntaxKind.TupleType] = _ => new this(); + } } // dprint-ignore @@ -2282,16 +2508,28 @@ export class AstNamedTupleMemberData extends AstTypeScriptNodeData { /** @internal */ jsDoc: JSDocArray | undefined = undefined; // initialized by parser (JSDocContainer) /** @internal */ symbol: Symbol = undefined!; // initialized by binder (Declaration) /** @internal */ localSymbol: Symbol | undefined = undefined; // initialized by binder (Declaration) + + static { + createDataInstanceMap[SyntaxKind.NamedTupleMember] = _ => new this(); + } } // dprint-ignore export class AstOptionalTypeNodeData extends AstTypeScriptNodeData { type: AstTypeNode = undefined!; + + static { + createDataInstanceMap[SyntaxKind.OptionalType] = _ => new this(); + } } // dprint-ignore export class AstRestTypeNodeData extends AstTypeScriptNodeData { type: AstTypeNode = undefined!; + + static { + createDataInstanceMap[SyntaxKind.RestType] = _ => new this(); + } } export type AstUnionOrIntersectionTypeNode = AstNodeOneOf; @@ -2299,11 +2537,19 @@ export type AstUnionOrIntersectionTypeNode = AstNodeOneOf = undefined!; + + static { + createDataInstanceMap[SyntaxKind.UnionType] = _ => new this(); + } } // dprint-ignore export class AstIntersectionTypeNodeData extends AstTypeScriptNodeData { types: AstNodeArray = undefined!; + + static { + createDataInstanceMap[SyntaxKind.IntersectionType] = _ => new this(); + } } // dprint-ignore @@ -2315,28 +2561,48 @@ export class AstConditionalTypeNodeData extends AstTypeScriptNodeData { /** @internal */ locals: SymbolTable | undefined = undefined; /** @internal */ nextContainer: AstHasLocals | undefined = undefined; + + static { + createDataInstanceMap[SyntaxKind.ConditionalType] = _ => new this(); + } } // dprint-ignore export class AstInferTypeNodeData extends AstTypeScriptNodeData { typeParameter: AstTypeParameterDeclaration = undefined!; + + static { + createDataInstanceMap[SyntaxKind.InferType] = _ => new this(); + } } // dprint-ignore export class AstParenthesizedTypeNodeData extends AstTypeScriptNodeData { type: AstTypeNode = undefined!; + + static { + createDataInstanceMap[SyntaxKind.ParenthesizedType] = _ => new this(); + } } // dprint-ignore export class AstTypeOperatorNodeData extends AstTypeScriptNodeData { operator: SyntaxKind.KeyOfKeyword | SyntaxKind.UniqueKeyword | SyntaxKind.ReadonlyKeyword = undefined!; type: AstTypeNode = undefined!; + + static { + createDataInstanceMap[SyntaxKind.TypeOperator] = _ => new this(); + } } // dprint-ignore export class AstIndexedAccessTypeNodeData extends AstTypeScriptNodeData { objectType: AstTypeNode = undefined!; indexType: AstTypeNode = undefined!; + + static { + createDataInstanceMap[SyntaxKind.IndexedAccessType] = _ => new this(); + } } // dprint-ignore @@ -2352,11 +2618,19 @@ export class AstMappedTypeNodeData extends AstTypeScriptNodeData { /** @internal */ localSymbol: Symbol | undefined = undefined; // initialized by binder (Declaration) /** @internal */ locals: SymbolTable | undefined = undefined; /** @internal */ nextContainer: AstHasLocals | undefined = undefined; + + static { + createDataInstanceMap[SyntaxKind.MappedType] = _ => new this(); + } } // dprint-ignore export class AstLiteralTypeNodeData extends AstTypeScriptNodeData { literal: AstNullLiteral | AstBooleanLiteral | AstLiteralExpression | AstPrefixUnaryExpression = undefined!; + + static { + createDataInstanceMap[SyntaxKind.LiteralType] = _ => new this(); + } } export type AstPropertyNameLiteral = AstNodeOneOf; @@ -2365,12 +2639,20 @@ export type AstPropertyNameLiteral = AstNodeOneOf; export class AstTemplateLiteralTypeNodeData extends AstTypeScriptNodeData { head: AstTemplateHead = undefined!; templateSpans: AstNodeArray = undefined!; + + static { + createDataInstanceMap[SyntaxKind.TemplateLiteralType] = _ => new this(); + } } // dprint-ignore export class AstTemplateLiteralTypeSpanData extends AstTypeScriptNodeData { type: AstTypeNode = undefined!; literal: AstTemplateMiddle | AstTemplateTail = undefined!; + + static { + createDataInstanceMap[SyntaxKind.TemplateLiteralTypeSpan] = _ => new this(); + } } // dprint-ignore @@ -2378,6 +2660,10 @@ export class AstOmittedExpressionData extends AstData { /** @internal */ override computeTransformFlags(_: AstNode): TransformFlags { return TransformFlags.None; } + + static { + createDataInstanceMap[SyntaxKind.OmittedExpression] = _ => new this(); + } } // dprint-ignore @@ -2400,6 +2686,10 @@ export class AstPrefixUnaryExpressionData extends AstData { } return transformFlags; } + + static { + createDataInstanceMap[SyntaxKind.PrefixUnaryExpression] = _ => new this(); + } } // dprint-ignore @@ -2421,6 +2711,10 @@ export class AstPostfixUnaryExpressionData extends AstData { } return transformFlags; } + + static { + createDataInstanceMap[SyntaxKind.PostfixUnaryExpression] = _ => new this(); + } } // dprint-ignore @@ -2430,6 +2724,10 @@ export class AstDeleteExpressionData extends AstData { /** @internal */ override computeTransformFlags(_: AstNode): TransformFlags { return propagateChildFlags(this.expression); } + + static { + createDataInstanceMap[SyntaxKind.DeleteExpression] = _ => new this(); + } } // dprint-ignore @@ -2439,6 +2737,10 @@ export class AstTypeOfExpressionData extends AstData { /** @internal */ override computeTransformFlags(_: AstNode): TransformFlags { return propagateChildFlags(this.expression); } + + static { + createDataInstanceMap[SyntaxKind.TypeOfExpression] = _ => new this(); + } } // dprint-ignore @@ -2448,6 +2750,10 @@ export class AstVoidExpressionData extends AstData { /** @internal */ override computeTransformFlags(_: AstNode): TransformFlags { return propagateChildFlags(this.expression); } + + static { + createDataInstanceMap[SyntaxKind.VoidExpression] = _ => new this(); + } } // dprint-ignore @@ -2460,6 +2766,10 @@ export class AstAwaitExpressionData extends AstData { TransformFlags.ContainsES2018 | TransformFlags.ContainsAwait; } + + static { + createDataInstanceMap[SyntaxKind.AwaitExpression] = _ => new this(); + } } // dprint-ignore @@ -2474,6 +2784,10 @@ export class AstYieldExpressionData extends AstData { TransformFlags.ContainsES2018 | TransformFlags.ContainsYield; } + + static { + createDataInstanceMap[SyntaxKind.YieldExpression] = _ => new this(); + } } export type AstBinaryOperatorToken = AstNode; @@ -2521,8 +2835,13 @@ export class AstBinaryExpressionData extends AstData { } return transformFlags; } + + static { + createDataInstanceMap[SyntaxKind.BinaryExpression] = _ => new this(); + } } +export type AstAssignmentExpression = AstNodeOneOf>; export type AstDestructuringAssignment = AstNodeOneOf; // dprint-ignore @@ -2540,6 +2859,10 @@ export class AstConditionalExpressionData extends AstData { propagateChildFlags(this.colonToken) | propagateChildFlags(this.whenFalse); } + + static { + createDataInstanceMap[SyntaxKind.ConditionalExpression] = _ => new this(); + } } export type AstFunctionBody = AstNodeOneOf; @@ -2583,6 +2906,10 @@ export class AstFunctionExpressionData extends AstData { (this.typeParameters || this.type ? TransformFlags.ContainsTypeScript : TransformFlags.None) | TransformFlags.ContainsHoistedDeclarationOrCompletion; } + + static { + createDataInstanceMap[SyntaxKind.FunctionExpression] = _ => new this(); + } } // dprint-ignore @@ -2616,6 +2943,10 @@ export class AstArrowFunctionData extends AstData { (isAsync ? TransformFlags.ContainsES2017 | TransformFlags.ContainsLexicalThis : TransformFlags.None) | TransformFlags.ContainsES2015; } + + static { + createDataInstanceMap[SyntaxKind.ArrowFunction] = _ => new this(); + } } // dprint-ignore @@ -2627,6 +2958,10 @@ export class AstRegularExpressionLiteralData extends AstTokenData { /** @internal */ override computeTransformFlags(_: AstNode): TransformFlags { return TransformFlags.None; } + + static { + createDataInstanceMap[SyntaxKind.RegularExpressionLiteral] = _ => new this(); + } } // dprint-ignore @@ -2643,6 +2978,10 @@ export class AstStringLiteralData extends AstTokenData { /** @internal */ override computeTransformFlags(_: AstNode): TransformFlags { return this.hasExtendedUnicodeEscape ? TransformFlags.ContainsES2015 : TransformFlags.None; } + + static { + createDataInstanceMap[SyntaxKind.StringLiteral] = _ => new this(); + } } // dprint-ignore @@ -2659,11 +2998,17 @@ export class AstNoSubstitutionTemplateLiteralData extends AstTokenData { /** @internal */ override computeTransformFlags(_: AstNode): TransformFlags { return getTransformFlagsOfTemplateLiteralLike(this.templateFlags); } + + static { + createDataInstanceMap[SyntaxKind.NoSubstitutionTemplateLiteral] = _ => new this(); + } } export type AstPseudoLiteralToken = AstNodeOneOf; export type AstTemplateLiteralToken = AstNodeOneOf; export type AstStringLiteralLike = AstNodeOneOf; +/** @internal */ +export type AstHasText = AstNodeOneOf; // dprint-ignore export class AstNumericLiteralData extends AstTokenData { @@ -2676,6 +3021,10 @@ export class AstNumericLiteralData extends AstTokenData { /** @internal */ override computeTransformFlags(_: AstNode): TransformFlags { return this.numericLiteralFlags & TokenFlags.BinaryOrOctalSpecifier ? TransformFlags.ContainsES2015 : TransformFlags.None; } + + static { + createDataInstanceMap[SyntaxKind.NumericLiteral] = _ => new this(); + } } // dprint-ignore @@ -2685,6 +3034,10 @@ export class AstBigIntLiteralData extends AstTokenData { /** @internal */ override computeTransformFlags(_: AstNode): TransformFlags { return TransformFlags.ContainsES2020; } + + static { + createDataInstanceMap[SyntaxKind.BigIntLiteral] = _ => new this(); + } } export type AstLiteralToken = AstNodeOneOf; @@ -2701,6 +3054,10 @@ export class AstTemplateHeadData extends AstTokenData { /** @internal */ override computeTransformFlags(_: AstNode): TransformFlags { return getTransformFlagsOfTemplateLiteralLike(this.templateFlags); } + + static { + createDataInstanceMap[SyntaxKind.TemplateHead] = _ => new this(); + } } // dprint-ignore @@ -2715,6 +3072,10 @@ export class AstTemplateMiddleData extends AstTokenData { /** @internal */ override computeTransformFlags(_: AstNode): TransformFlags { return getTransformFlagsOfTemplateLiteralLike(this.templateFlags); } + + static { + createDataInstanceMap[SyntaxKind.TemplateMiddle] = _ => new this(); + } } // dprint-ignore @@ -2729,6 +3090,10 @@ export class AstTemplateTailData extends AstTokenData { /** @internal */ override computeTransformFlags(_: AstNode): TransformFlags { return getTransformFlagsOfTemplateLiteralLike(this.templateFlags); } + + static { + createDataInstanceMap[SyntaxKind.TemplateTail] = _ => new this(); + } } // dprint-ignore @@ -2741,6 +3106,10 @@ export class AstTemplateExpressionData extends AstData { propagateChildrenFlags(this.templateSpans) | TransformFlags.ContainsES2015; } + static { + createDataInstanceMap[SyntaxKind.TemplateExpression] = _ => new this(); + } + } // dprint-ignore @@ -2753,6 +3122,10 @@ export class AstTemplateSpanData extends AstData { propagateChildFlags(this.literal) | TransformFlags.ContainsES2015; } + + static { + createDataInstanceMap[SyntaxKind.TemplateSpan] = _ => new this(); + } } // dprint-ignore @@ -2763,6 +3136,10 @@ export class AstParenthesizedExpressionData extends AstData { /** @internal */ override computeTransformFlags(_: AstNode): TransformFlags { return propagateChildFlags(this.expression); } + + static { + createDataInstanceMap[SyntaxKind.ParenthesizedExpression] = _ => new this(); + } } /** @internal */ @@ -2777,6 +3154,10 @@ export class AstArrayLiteralExpressionData extends AstData { /** @internal */ override computeTransformFlags(_: AstNode): TransformFlags { return propagateChildrenFlags(this.elements); } + + static { + createDataInstanceMap[SyntaxKind.ArrayLiteralExpression] = _ => new this(); + } } // dprint-ignore @@ -2788,6 +3169,10 @@ export class AstSpreadElementData extends AstData { TransformFlags.ContainsES2015 | TransformFlags.ContainsRestOrSpread; } + + static { + createDataInstanceMap[SyntaxKind.SpreadElement] = _ => new this(); + } } export type AstObjectLiteralElement = AstNode; @@ -2805,6 +3190,10 @@ export class AstObjectLiteralExpressionData extends AstData { /** @internal */ override computeTransformFlags(_: AstNode): TransformFlags { return propagateChildrenFlags(this.properties); } + + static { + createDataInstanceMap[SyntaxKind.ObjectLiteralExpression] = _ => new this(); + } } export type AstPropertyAccessExpression = AstNode; @@ -2837,9 +3226,14 @@ export class AstPropertyAccessExpressionData extends AstData { } return transformFlags; } + + static { + createDataInstanceMap[SyntaxKind.PropertyAccessExpression] = _ => new this(); + } } export type AstPropertyAccessEntityNameExpression = AstNode; +export type AstAccessExpression = AstNodeOneOf; export type AstEntityNameExpression = AstNodeOneOf; export type AstPropertyAccessChain = AstNode; /** @internal */ @@ -2871,6 +3265,10 @@ export class AstElementAccessExpressionData extends AstData { } return transformFlags; } + + static { + createDataInstanceMap[SyntaxKind.ElementAccessExpression] = _ => new this(); + } } export type AstElementAccessChain = AstNode; @@ -2896,9 +3294,9 @@ export class AstCallExpressionData extends AstData { transformFlags |= TransformFlags.ContainsTypeScript; } if ( - (this.expression.kind === SyntaxKind.PropertyAccessExpression || - this.expression.kind === SyntaxKind.ElementAccessExpression) && - (this.expression as AstNode).data.expression.kind === SyntaxKind.SuperKeyword + (astIsPropertyAccessExpression(this.expression) || + astIsElementAccessExpression(this.expression)) && + astGetExpression(this.expression).kind === SyntaxKind.SuperKeyword ) { transformFlags |= TransformFlags.ContainsLexicalThis; } @@ -2910,6 +3308,10 @@ export class AstCallExpressionData extends AstData { } return transformFlags; } + + static { + createDataInstanceMap[SyntaxKind.CallExpression] = _ => new this(); + } } export type AstCallChain = AstNode; @@ -2917,6 +3319,20 @@ export type AstCallChain = AstNode; export type AstCallChainRoot = AstNode; /** @internal */ export type AstOptionalChainRoot = AstNodeOneOf; +/** @internal */ +export type AstLiteralLikeElementAccessExpression = AstNodeOneOf; +/** @internal */ +export type AstBindableStaticNameExpression = AstNodeOneOf; +/** @internal */ +export type AstBindableStaticAccessExpression = AstNodeOneOf; +/** @internal */ +export type AstBindableStaticPropertyAssignmentExpression = AstNodeOneOf; +/** @internal */ +export type AstBindableStaticElementAccessExpression = AstNodeOneOf; +/** @internal */ +export type AstBindablePropertyAssignmentExpression = AstNodeOneOf; +/** @internal */ +export type AstBindableObjectDefinePropertyCall = AstNodeOneOf; // dprint-ignore export class AstExpressionWithTypeArgumentsData extends AstData { @@ -2928,6 +3344,10 @@ export class AstExpressionWithTypeArgumentsData extends AstData { propagateChildrenFlags(this.typeArguments) | TransformFlags.ContainsES2015; } + + static { + createDataInstanceMap[SyntaxKind.ExpressionWithTypeArguments] = _ => new this(); + } } // dprint-ignore @@ -2949,6 +3369,10 @@ export class AstNewExpressionData extends AstData { } return transformFlags; } + + static { + createDataInstanceMap[SyntaxKind.NewExpression] = _ => new this(); + } } export type AstTemplateLiteral = AstNodeOneOf; @@ -2973,6 +3397,10 @@ export class AstTaggedTemplateExpressionData extends AstData { } return transformFlags; } + + static { + createDataInstanceMap[SyntaxKind.TaggedTemplateExpression] = _ => new this(); + } } // dprint-ignore @@ -2985,10 +3413,14 @@ export class AstAsExpressionData extends AstData { propagateChildFlags(this.type) | TransformFlags.ContainsTypeScript; } + + static { + createDataInstanceMap[SyntaxKind.AsExpression] = _ => new this(); + } } // dprint-ignore -export class AstTypeAssertionData extends AstData { +export class AstTypeAssertionExpressionData extends AstData { type: AstTypeNode = undefined!; expression: AstUnaryExpression = undefined!; @@ -2997,6 +3429,10 @@ export class AstTypeAssertionData extends AstData { propagateChildFlags(this.type) | TransformFlags.ContainsTypeScript; } + + static { + createDataInstanceMap[SyntaxKind.TypeAssertionExpression] = _ => new this(); + } } // dprint-ignore @@ -3009,6 +3445,10 @@ export class AstSatisfiesExpressionData extends AstData { propagateChildFlags(this.type) | TransformFlags.ContainsTypeScript; } + + static { + createDataInstanceMap[SyntaxKind.SatisfiesExpression] = _ => new this(); + } } // dprint-ignore @@ -3019,6 +3459,10 @@ export class AstNonNullExpressionData extends AstData { return propagateChildFlags(this.expression) | TransformFlags.ContainsTypeScript; } + + static { + createDataInstanceMap[SyntaxKind.NonNullExpression] = _ => new this(); + } } export type AstNonNullChain = AstNode; @@ -3044,6 +3488,10 @@ export class AstMetaPropertyData extends AstData { } return transformFlags; } + + static { + createDataInstanceMap[SyntaxKind.MetaProperty] = _ => new this(); + } } // dprint-ignore @@ -3058,6 +3506,10 @@ export class AstJsxElementData extends AstData { propagateChildFlags(this.closingElement) | TransformFlags.ContainsJsx; } + + static { + createDataInstanceMap[SyntaxKind.JsxElement] = _ => new this(); + } } export type AstJsxOpeningLikeElement = AstNodeOneOf; @@ -3081,6 +3533,10 @@ export class AstJsxAttributesData extends AstData { return propagateChildrenFlags(this.properties) | TransformFlags.ContainsJsx; } + + static { + createDataInstanceMap[SyntaxKind.JsxAttributes] = _ => new this(); + } } // dprint-ignore @@ -3093,6 +3549,10 @@ export class AstJsxNamespacedNameData extends AstData { propagateChildFlags(this.name) | TransformFlags.ContainsJsx; } + + static { + createDataInstanceMap[SyntaxKind.JsxNamespacedName] = _ => new this(); + } } // dprint-ignore @@ -3111,6 +3571,10 @@ export class AstJsxOpeningElementData extends AstData { } return transformFlags; } + + static { + createDataInstanceMap[SyntaxKind.JsxOpeningElement] = _ => new this(); + } } // dprint-ignore @@ -3121,6 +3585,10 @@ export class AstJsxClosingElementData extends AstData { return propagateChildFlags(this.tagName) | TransformFlags.ContainsJsx; } + + static { + createDataInstanceMap[SyntaxKind.JsxClosingElement] = _ => new this(); + } } // dprint-ignore @@ -3139,6 +3607,10 @@ export class AstJsxSelfClosingElementData extends AstData { } return transformFlags; } + + static { + createDataInstanceMap[SyntaxKind.JsxSelfClosingElement] = _ => new this(); + } } // dprint-ignore @@ -3153,6 +3625,10 @@ export class AstJsxFragmentData extends AstData { propagateChildFlags(this.closingFragment) | TransformFlags.ContainsJsx; } + + static { + createDataInstanceMap[SyntaxKind.JsxFragment] = _ => new this(); + } } // dprint-ignore @@ -3160,6 +3636,10 @@ export class AstJsxOpeningFragmentData extends AstData { /** @internal */ override computeTransformFlags(_: AstNode): TransformFlags { return TransformFlags.ContainsJsx; } + + static { + createDataInstanceMap[SyntaxKind.JsxOpeningFragment] = _ => new this(); + } } // dprint-ignore @@ -3167,6 +3647,10 @@ export class AstJsxClosingFragmentData extends AstData { /** @internal */ override computeTransformFlags(_: AstNode): TransformFlags { return TransformFlags.ContainsJsx; } + + static { + createDataInstanceMap[SyntaxKind.JsxClosingFragment] = _ => new this(); + } } // dprint-ignore @@ -3182,6 +3666,10 @@ export class AstJsxAttributeData extends AstData { propagateChildFlags(this.initializer) | TransformFlags.ContainsJsx; } + + static { + createDataInstanceMap[SyntaxKind.JsxAttribute] = _ => new this(); + } } export type AstJsxAttributeValue = AstNodeOneOf; @@ -3194,6 +3682,10 @@ export class AstJsxSpreadAttributeData extends AstData { return propagateChildFlags(this.expression) | TransformFlags.ContainsJsx; } + + static { + createDataInstanceMap[SyntaxKind.JsxSpreadAttribute] = _ => new this(); + } } // dprint-ignore @@ -3206,6 +3698,10 @@ export class AstJsxExpressionData extends AstData { propagateChildFlags(this.expression) | TransformFlags.ContainsJsx; } + + static { + createDataInstanceMap[SyntaxKind.JsxExpression] = _ => new this(); + } } // dprint-ignore @@ -3218,6 +3714,10 @@ export class AstJsxTextData extends AstData { /** @internal */ override computeTransformFlags(_: AstNode): TransformFlags { return TransformFlags.ContainsJsx; } + + static { + createDataInstanceMap[SyntaxKind.JsxText] = _ => new this(); + } } export type AstJsxChild = AstNodeOneOf; @@ -3230,6 +3730,10 @@ export class AstEmptyStatementData extends AstData { /** @internal */ override computeTransformFlags(_: AstNode): TransformFlags { return TransformFlags.None; } + + static { + createDataInstanceMap[SyntaxKind.EmptyStatement] = _ => new this(); + } } // dprint-ignore @@ -3240,6 +3744,10 @@ export class AstDebuggerStatementData extends AstData { /** @internal */ override computeTransformFlags(_: AstNode): TransformFlags { return TransformFlags.None; } + + static { + createDataInstanceMap[SyntaxKind.DebuggerStatement] = _ => new this(); + } } // dprint-ignore @@ -3254,6 +3762,10 @@ export class AstMissingDeclarationData extends AstData { /** @internal */ override computeTransformFlags(_: AstNode): TransformFlags { return TransformFlags.None; } + + static { + createDataInstanceMap[SyntaxKind.MissingDeclaration] = _ => new this(); + } } // dprint-ignore @@ -3268,6 +3780,10 @@ export class AstBlockData extends AstData { /** @internal */ override computeTransformFlags(_: AstNode): TransformFlags { return propagateChildrenFlags(this.statements); } + + static { + createDataInstanceMap[SyntaxKind.Block] = _ => new this(); + } } // dprint-ignore @@ -3286,8 +3802,15 @@ export class AstVariableStatementData extends AstData { } return transformFlags; } + + static { + createDataInstanceMap[SyntaxKind.VariableStatement] = _ => new this(); + } } +/** @internal */ +export type AstPrologueDirective = AstNodeOneOf; + // dprint-ignore export class AstExpressionStatementData extends AstData { expression: AstExpression = undefined!; @@ -3298,6 +3821,10 @@ export class AstExpressionStatementData extends AstData { /** @internal */ override computeTransformFlags(_: AstNode): TransformFlags { return propagateChildFlags(this.expression); } + + static { + createDataInstanceMap[SyntaxKind.ExpressionStatement] = _ => new this(); + } } // dprint-ignore @@ -3314,6 +3841,10 @@ export class AstIfStatementData extends AstData { propagateChildFlags(this.thenStatement) | propagateChildFlags(this.elseStatement); } + + static { + createDataInstanceMap[SyntaxKind.IfStatement] = _ => new this(); + } } // dprint-ignore @@ -3328,6 +3859,10 @@ export class AstDoStatementData extends AstData { return propagateChildFlags(this.statement) | propagateChildFlags(this.expression); } + + static { + createDataInstanceMap[SyntaxKind.DoStatement] = _ => new this(); + } } // dprint-ignore @@ -3342,6 +3877,10 @@ export class AstWhileStatementData extends AstData { return propagateChildFlags(this.expression) | propagateChildFlags(this.statement); } + + static { + createDataInstanceMap[SyntaxKind.WhileStatement] = _ => new this(); + } } export type AstForInitializer = AstNodeOneOf; @@ -3364,6 +3903,10 @@ export class AstForStatementData extends AstData { propagateChildFlags(this.incrementor) | propagateChildFlags(this.statement); } + + static { + createDataInstanceMap[SyntaxKind.ForStatement] = _ => new this(); + } } export type AstForInOrOfStatement = AstNodeOneOf; @@ -3384,6 +3927,10 @@ export class AstForInStatementData extends AstData { propagateChildFlags(this.expression) | propagateChildFlags(this.statement); } + + static { + createDataInstanceMap[SyntaxKind.ForInStatement] = _ => new this(); + } } // dprint-ignore @@ -3409,6 +3956,10 @@ export class AstForOfStatementData extends AstData { } return transformFlags; } + + static { + createDataInstanceMap[SyntaxKind.ForOfStatement] = _ => new this(); + } } // dprint-ignore @@ -3422,6 +3973,10 @@ export class AstBreakStatementData extends AstData { return propagateChildFlags(this.label) | TransformFlags.ContainsHoistedDeclarationOrCompletion; } + + static { + createDataInstanceMap[SyntaxKind.BreakStatement] = _ => new this(); + } } export type AstBreakOrContinueStatement = AstNodeOneOf; @@ -3437,6 +3992,10 @@ export class AstContinueStatementData extends AstData { return propagateChildFlags(this.label) | TransformFlags.ContainsHoistedDeclarationOrCompletion; } + + static { + createDataInstanceMap[SyntaxKind.ContinueStatement] = _ => new this(); + } } // dprint-ignore @@ -3452,6 +4011,10 @@ export class AstReturnStatementData extends AstData { TransformFlags.ContainsES2018 | TransformFlags.ContainsHoistedDeclarationOrCompletion; } + + static { + createDataInstanceMap[SyntaxKind.ReturnStatement] = _ => new this(); + } } // dprint-ignore @@ -3466,6 +4029,10 @@ export class AstWithStatementData extends AstData { return propagateChildFlags(this.expression) | propagateChildFlags(this.statement); } + + static { + createDataInstanceMap[SyntaxKind.WithStatement] = _ => new this(); + } } // dprint-ignore @@ -3481,6 +4048,10 @@ export class AstSwitchStatementData extends AstData { return propagateChildFlags(this.expression) | propagateChildFlags(this.caseBlock); } + + static { + createDataInstanceMap[SyntaxKind.SwitchStatement] = _ => new this(); + } } // dprint-ignore @@ -3493,6 +4064,10 @@ export class AstCaseBlockData extends AstData { /** @internal */ override computeTransformFlags(_: AstNode): TransformFlags { return propagateChildrenFlags(this.clauses); } + + static { + createDataInstanceMap[SyntaxKind.CaseBlock] = _ => new this(); + } } // dprint-ignore @@ -3507,6 +4082,10 @@ export class AstCaseClauseData extends AstData { return propagateChildFlags(this.expression) | propagateChildrenFlags(this.statements); } + + static { + createDataInstanceMap[SyntaxKind.CaseClause] = _ => new this(); + } } // dprint-ignore @@ -3518,6 +4097,10 @@ export class AstDefaultClauseData extends AstData { /** @internal */ override computeTransformFlags(_: AstNode): TransformFlags { return propagateChildrenFlags(this.statements); } + + static { + createDataInstanceMap[SyntaxKind.DefaultClause] = _ => new this(); + } } export type AstCaseOrDefaultClause = AstNodeOneOf; @@ -3534,6 +4117,10 @@ export class AstLabeledStatementData extends AstData { return propagateChildFlags(this.label) | propagateChildFlags(this.statement); } + + static { + createDataInstanceMap[SyntaxKind.LabeledStatement] = _ => new this(); + } } // dprint-ignore @@ -3546,6 +4133,10 @@ export class AstThrowStatementData extends AstData { /** @internal */ override computeTransformFlags(_: AstNode): TransformFlags { return propagateChildFlags(this.expression); } + + static { + createDataInstanceMap[SyntaxKind.ThrowStatement] = _ => new this(); + } } // dprint-ignore @@ -3562,6 +4153,10 @@ export class AstTryStatementData extends AstData { propagateChildFlags(this.catchClause) | propagateChildFlags(this.finallyBlock); } + + static { + createDataInstanceMap[SyntaxKind.TryStatement] = _ => new this(); + } } // dprint-ignore @@ -3577,6 +4172,10 @@ export class AstCatchClauseData extends AstData { propagateChildFlags(this.block) | (!this.variableDeclaration ? TransformFlags.ContainsES2019 : TransformFlags.None); } + + static { + createDataInstanceMap[SyntaxKind.CatchClause] = _ => new this(); + } } export type AstObjectTypeDeclaration = AstNodeOneOf; @@ -3615,6 +4214,10 @@ export class AstClassDeclarationData extends AstData { return transformFlags; } } + + static { + createDataInstanceMap[SyntaxKind.ClassDeclaration] = _ => new this(); + } } // dprint-ignore @@ -3638,6 +4241,10 @@ export class AstClassExpressionData extends AstData { (this.typeParameters ? TransformFlags.ContainsTypeScript : TransformFlags.None) | TransformFlags.ContainsES2015; } + + static { + createDataInstanceMap[SyntaxKind.ClassExpression] = _ => new this(); + } } export type AstTypeElement = AstNode; @@ -3653,6 +4260,10 @@ export class AstInterfaceDeclarationData extends AstTypeScriptNodeData { /** @internal */ jsDoc: JSDocArray | undefined = undefined; // initialized by parser (JSDocContainer) /** @internal */ symbol: Symbol = undefined!; // initialized by binder (Declaration) /** @internal */ localSymbol: Symbol | undefined = undefined; // initialized by binder (Declaration) + + static { + createDataInstanceMap[SyntaxKind.InterfaceDeclaration] = _ => new this(); + } } // dprint-ignore @@ -3670,6 +4281,10 @@ export class AstHeritageClauseData extends AstData { return Debug.assertNever(this.token); } } + + static { + createDataInstanceMap[SyntaxKind.HeritageClause] = _ => new this(); + } } // dprint-ignore @@ -3684,6 +4299,10 @@ export class AstTypeAliasDeclarationData extends AstTypeScriptNodeData { /** @internal */ localSymbol: Symbol | undefined = undefined; // initialized by binder (Declaration) /** @internal */ locals: SymbolTable | undefined = undefined; /** @internal */ nextContainer: AstHasLocals | undefined = undefined; + + static { + createDataInstanceMap[SyntaxKind.TypeAliasDeclaration] = _ => new this(); + } } // dprint-ignore @@ -3704,6 +4323,10 @@ export class AstEnumDeclarationData extends AstData { transformFlags &= ~TransformFlags.ContainsPossibleTopLevelAwait; // Enum declarations cannot contain `await` return transformFlags; } + + static { + createDataInstanceMap[SyntaxKind.EnumDeclaration] = _ => new this(); + } } // dprint-ignore @@ -3720,6 +4343,10 @@ export class AstEnumMemberData extends AstData { propagateChildFlags(this.initializer) | TransformFlags.ContainsTypeScript; } + + static { + createDataInstanceMap[SyntaxKind.EnumMember] = _ => new this(); + } } export type AstModuleName = AstNodeOneOf; @@ -3750,8 +4377,17 @@ export class AstModuleDeclarationData extends AstData { return transformFlags; } } + + static { + createDataInstanceMap[SyntaxKind.ModuleDeclaration] = _ => new this(); + } } +/** @internal */ +export type AstAmbientModuleDeclaration = AstNodeOneOf; +/** @internal */ +export type AstNonGlobalAmbientModuleDeclaration = AstNodeOneOf; + export type AstNamespaceBody = AstNodeOneOf; export type AstNamespaceDeclaration = AstNode; @@ -3779,6 +4415,10 @@ export class AstModuleBlockData extends AstData { /** @internal */ override computeTransformFlags(_: AstNode): TransformFlags { return propagateChildrenFlags(this.statements); } + + static { + createDataInstanceMap[SyntaxKind.ModuleBlock] = _ => new this(); + } } export type AstModuleReference = AstNodeOneOf; @@ -3805,6 +4445,10 @@ export class AstImportEqualsDeclarationData extends AstData { return transformFlags & ~TransformFlags.ContainsPossibleTopLevelAwait; // Import= declaration is always parsed in an Await context } + + static { + createDataInstanceMap[SyntaxKind.ImportEqualsDeclaration] = _ => new this(); + } } // dprint-ignore @@ -3815,6 +4459,10 @@ export class AstExternalModuleReferenceData extends AstData { // always parsed in an Await context return propagateChildFlags(this.expression) & ~TransformFlags.ContainsPossibleTopLevelAwait; } + + static { + createDataInstanceMap[SyntaxKind.ExternalModuleReference] = _ => new this(); + } } // dprint-ignore @@ -3835,6 +4483,10 @@ export class AstImportDeclarationData extends AstData { transformFlags &= ~TransformFlags.ContainsPossibleTopLevelAwait; // always parsed in an Await context return transformFlags; } + + static { + createDataInstanceMap[SyntaxKind.ImportDeclaration] = _ => new this(); + } } export type AstNamedImportBindings = AstNodeOneOf; @@ -3858,6 +4510,10 @@ export class AstImportClauseData extends AstData { transformFlags &= ~TransformFlags.ContainsPossibleTopLevelAwait; // always parsed in an Await context return transformFlags; } + + static { + createDataInstanceMap[SyntaxKind.ImportClause] = _ => new this(); + } } export type AstAssertionKey = AstNodeOneOf; @@ -3873,6 +4529,10 @@ export class AstImportAttributeData extends AstData { /** @internal */ override computeTransformFlags(_: AstNode): TransformFlags { return TransformFlags.ContainsESNext; } + + static { + createDataInstanceMap[SyntaxKind.ImportAttribute] = _ => new this(); + } } /** @deprecated */ @@ -3887,6 +4547,10 @@ export class AstImportAttributesData extends AstData { /** @internal */ override computeTransformFlags(_: AstNode): TransformFlags { return TransformFlags.ContainsESNext; } + + static { + createDataInstanceMap[SyntaxKind.ImportAttributes] = _ => new this(); + } } // dprint-ignore @@ -3901,6 +4565,10 @@ export class AstNamespaceImportData extends AstData { transformFlags &= ~TransformFlags.ContainsPossibleTopLevelAwait; // always parsed in an Await context return transformFlags; } + + static { + createDataInstanceMap[SyntaxKind.NamespaceImport] = _ => new this(); + } } // dprint-ignore @@ -3916,6 +4584,10 @@ export class AstNamespaceExportData extends AstData { transformFlags &= ~TransformFlags.ContainsPossibleTopLevelAwait; // always parsed in an Await context return transformFlags; } + + static { + createDataInstanceMap[SyntaxKind.NamespaceExport] = _ => new this(); + } } // dprint-ignore @@ -3931,6 +4603,10 @@ export class AstNamespaceExportDeclarationData extends AstData { return propagateIdentifierNameFlags(this.name) | TransformFlags.ContainsTypeScript; } + + static { + createDataInstanceMap[SyntaxKind.NamespaceExportDeclaration] = _ => new this(); + } } // dprint-ignore @@ -3952,6 +4628,10 @@ export class AstExportDeclarationData extends AstData { transformFlags &= ~TransformFlags.ContainsPossibleTopLevelAwait; // always parsed in an Await context return transformFlags; } + + static { + createDataInstanceMap[SyntaxKind.ExportDeclaration] = _ => new this(); + } } // dprint-ignore @@ -3963,6 +4643,10 @@ export class AstNamedImportsData extends AstData { transformFlags &= ~TransformFlags.ContainsPossibleTopLevelAwait; // always parsed in an Await context return transformFlags; } + + static { + createDataInstanceMap[SyntaxKind.NamedImports] = _ => new this(); + } } // dprint-ignore @@ -3974,6 +4658,10 @@ export class AstNamedExportsData extends AstData { transformFlags &= ~TransformFlags.ContainsPossibleTopLevelAwait; // always parsed in an Await context return transformFlags; } + + static { + createDataInstanceMap[SyntaxKind.NamedExports] = _ => new this(); + } } // dprint-ignore @@ -3991,6 +4679,10 @@ export class AstImportSpecifierData extends AstData { transformFlags &= ~TransformFlags.ContainsPossibleTopLevelAwait; // always parsed in an Await context return transformFlags; } + + static { + createDataInstanceMap[SyntaxKind.ImportSpecifier] = _ => new this(); + } } // dprint-ignore @@ -4009,6 +4701,10 @@ export class AstExportSpecifierData extends AstData { transformFlags &= ~TransformFlags.ContainsPossibleTopLevelAwait; // always parsed in an Await context return transformFlags; } + + static { + createDataInstanceMap[SyntaxKind.ExportSpecifier] = _ => new this(); + } } export type AstModuleExportName = AstNodeOneOf; @@ -4028,49 +4724,85 @@ export class AstExportAssignmentData extends AstData { transformFlags &= ~TransformFlags.ContainsPossibleTopLevelAwait; // always parsed in an Await context return transformFlags; } + + static { + createDataInstanceMap[SyntaxKind.ExportAssignment] = _ => new this(); + } } // dprint-ignore export class AstJSDocTypeExpressionData extends AstData { type: AstTypeNode = undefined!; + + static { + createDataInstanceMap[SyntaxKind.JSDocTypeExpression] = _ => new this(); + } } // dprint-ignore export class AstJSDocNameReferenceData extends AstData { name: AstEntityName | AstJSDocMemberName = undefined!; + + static { + createDataInstanceMap[SyntaxKind.JSDocNameReference] = _ => new this(); + } } // dprint-ignore export class AstJSDocMemberNameData extends AstData { left: AstEntityName | AstJSDocMemberName = undefined!; right: AstIdentifier = undefined!; + + static { + createDataInstanceMap[SyntaxKind.JSDocMemberName] = _ => new this(); + } } export type AstJSDocType = AstNodeOneOf; // dprint-ignore export class AstJSDocAllTypeData extends AstData { + + static { + createDataInstanceMap[SyntaxKind.JSDocAllType] = _ => new this(); + } } // dprint-ignore export class AstJSDocUnknownTypeData extends AstData { + + static { + createDataInstanceMap[SyntaxKind.JSDocUnknownType] = _ => new this(); + } } // dprint-ignore export class AstJSDocNonNullableTypeData extends AstData { type: AstTypeNode = undefined!; postfix = false; + + static { + createDataInstanceMap[SyntaxKind.JSDocNonNullableType] = _ => new this(); + } } // dprint-ignore export class AstJSDocNullableTypeData extends AstData { type: AstTypeNode = undefined!; postfix = false; + + static { + createDataInstanceMap[SyntaxKind.JSDocNullableType] = _ => new this(); + } } // dprint-ignore export class AstJSDocOptionalTypeData extends AstData { type: AstTypeNode = undefined!; + + static { + createDataInstanceMap[SyntaxKind.JSDocOptionalType] = _ => new this(); + } } // dprint-ignore @@ -4085,22 +4817,39 @@ export class AstJSDocFunctionTypeData extends AstData { /** @internal */ localSymbol: Symbol | undefined = undefined; // initialized by binder (Declaration) /** @internal */ locals: SymbolTable | undefined = undefined; /** @internal */ nextContainer: AstHasLocals | undefined = undefined; + + static { + createDataInstanceMap[SyntaxKind.JSDocFunctionType] = _ => new this(); + } } // dprint-ignore export class AstJSDocVariadicTypeData extends AstData { type: AstTypeNode = undefined!; + + static { + createDataInstanceMap[SyntaxKind.JSDocVariadicType] = _ => new this(); + } } // dprint-ignore export class AstJSDocNamepathTypeData extends AstData { type: AstTypeNode = undefined!; + + static { + createDataInstanceMap[SyntaxKind.JSDocNamepathType] = _ => new this(); + } } // dprint-ignore export class AstJSDocData extends AstData { - comment: string | AstNodeArray | undefined = undefined; + comment: string | undefined = undefined; + commentArray: AstNodeArray | undefined = undefined; tags: AstNodeArray | undefined = undefined; + + static { + createDataInstanceMap[SyntaxKind.JSDoc] = _ => new this(); + } } export type AstHasJSDoc = AstNodeOneOf; @@ -4110,18 +4859,30 @@ export type AstJSDocTag = AstNodeOneOf; export class AstJSDocLinkData extends AstData { name: AstEntityName | AstJSDocMemberName | undefined = undefined; text = ""; + + static { + createDataInstanceMap[SyntaxKind.JSDocLink] = _ => new this(); + } } // dprint-ignore export class AstJSDocLinkCodeData extends AstData { name: AstEntityName | AstJSDocMemberName | undefined = undefined; text = ""; + + static { + createDataInstanceMap[SyntaxKind.JSDocLinkCode] = _ => new this(); + } } // dprint-ignore export class AstJSDocLinkPlainData extends AstData { name: AstEntityName | AstJSDocMemberName | undefined = undefined; text = ""; + + static { + createDataInstanceMap[SyntaxKind.JSDocLinkPlain] = _ => new this(); + } } export type AstJSDocComment = AstNodeOneOf; @@ -4129,14 +4890,19 @@ export type AstJSDocComment = AstNodeOneOf; // dprint-ignore export class AstJSDocTextData extends AstData { text = ""; + + static { + createDataInstanceMap[SyntaxKind.JSDocText] = _ => new this(); + } } export type AstBaseJSDocTag = AstNode>; // dprint-ignore -export class AstJSDocTagData extends AstData { - tagName: AstIdentifier = undefined!; - comment: string | AstNodeArray | undefined = undefined; +export abstract class AstJSDocTagData extends AstData { + abstract tagName: AstIdentifier; + abstract comment: string | undefined; + abstract commentArray: AstNodeArray | undefined; /** @internal */ override computeTransformFlags(_: AstNode): TransformFlags { return TransformFlags.None; @@ -4145,6 +4911,13 @@ export class AstJSDocTagData extends AstData { // dprint-ignore export class AstJSDocUnknownTagData extends AstJSDocTagData { + tagName: AstIdentifier = undefined!; + comment: string | undefined = undefined; + commentArray: AstNodeArray | undefined = undefined; + + static { + createDataInstanceMap[SyntaxKind.JSDocTag] = _ => new this(); + } } export type AstJSDocClassReference = AstNode; @@ -4155,84 +4928,193 @@ export interface AstJSDocClassReferenceData extends AstExpressionWithTypeArgumen // dprint-ignore export class AstJSDocAugmentsTagData extends AstJSDocTagData { + tagName: AstIdentifier = undefined!; + comment: string | undefined = undefined; + commentArray: AstNodeArray | undefined = undefined; class: AstJSDocClassReference = undefined!; + + static { + createDataInstanceMap[SyntaxKind.JSDocAugmentsTag] = _ => new this(); + } } // dprint-ignore export class AstJSDocImplementsTagData extends AstJSDocTagData { + tagName: AstIdentifier = undefined!; + comment: string | undefined = undefined; + commentArray: AstNodeArray | undefined = undefined; class: AstJSDocClassReference = undefined!; + + static { + createDataInstanceMap[SyntaxKind.JSDocImplementsTag] = _ => new this(); + } } // dprint-ignore export class AstJSDocAuthorTagData extends AstJSDocTagData { + tagName: AstIdentifier = undefined!; + comment: string | undefined = undefined; + commentArray: AstNodeArray | undefined = undefined; + + static { + createDataInstanceMap[SyntaxKind.JSDocAuthorTag] = _ => new this(); + } } // dprint-ignore export class AstJSDocDeprecatedTagData extends AstJSDocTagData { + tagName: AstIdentifier = undefined!; + comment: string | undefined = undefined; + commentArray: AstNodeArray | undefined = undefined; + + static { + createDataInstanceMap[SyntaxKind.JSDocDeprecatedTag] = _ => new this(); + } } // dprint-ignore export class AstJSDocClassTagData extends AstJSDocTagData { + tagName: AstIdentifier = undefined!; + comment: string | undefined = undefined; + commentArray: AstNodeArray | undefined = undefined; + + static { + createDataInstanceMap[SyntaxKind.JSDocClassTag] = _ => new this(); + } } // dprint-ignore export class AstJSDocPublicTagData extends AstJSDocTagData { + tagName: AstIdentifier = undefined!; + comment: string | undefined = undefined; + commentArray: AstNodeArray | undefined = undefined; + + static { + createDataInstanceMap[SyntaxKind.JSDocPublicTag] = _ => new this(); + } } // dprint-ignore export class AstJSDocPrivateTagData extends AstJSDocTagData { + tagName: AstIdentifier = undefined!; + comment: string | undefined = undefined; + commentArray: AstNodeArray | undefined = undefined; + + static { + createDataInstanceMap[SyntaxKind.JSDocPrivateTag] = _ => new this(); + } } // dprint-ignore export class AstJSDocProtectedTagData extends AstJSDocTagData { + tagName: AstIdentifier = undefined!; + comment: string | undefined = undefined; + commentArray: AstNodeArray | undefined = undefined; + + static { + createDataInstanceMap[SyntaxKind.JSDocProtectedTag] = _ => new this(); + } } // dprint-ignore export class AstJSDocReadonlyTagData extends AstJSDocTagData { + tagName: AstIdentifier = undefined!; + comment: string | undefined = undefined; + commentArray: AstNodeArray | undefined = undefined; + + static { + createDataInstanceMap[SyntaxKind.JSDocReadonlyTag] = _ => new this(); + } } // dprint-ignore export class AstJSDocOverrideTagData extends AstJSDocTagData { + tagName: AstIdentifier = undefined!; + comment: string | undefined = undefined; + commentArray: AstNodeArray | undefined = undefined; + + static { + createDataInstanceMap[SyntaxKind.JSDocOverrideTag] = _ => new this(); + } } // dprint-ignore export class AstJSDocEnumTagData extends AstJSDocTagData { + tagName: AstIdentifier = undefined!; + comment: string | undefined = undefined; + commentArray: AstNodeArray | undefined = undefined; typeExpression: AstJSDocTypeExpression = undefined!; /** @internal */ symbol: Symbol = undefined!; // initialized by binder (Declaration) /** @internal */ localSymbol: Symbol | undefined = undefined; // initialized by binder (Declaration) /** @internal */ locals: SymbolTable | undefined = undefined; /** @internal */ nextContainer: AstHasLocals | undefined = undefined; + static { + createDataInstanceMap[SyntaxKind.JSDocEnumTag] = _ => new this(); + } } // dprint-ignore export class AstJSDocThisTagData extends AstJSDocTagData { + tagName: AstIdentifier = undefined!; + comment: string | undefined = undefined; + commentArray: AstNodeArray | undefined = undefined; typeExpression: AstJSDocTypeExpression = undefined!; + static { + createDataInstanceMap[SyntaxKind.JSDocThisTag] = _ => new this(); + } } // dprint-ignore export class AstJSDocTemplateTagData extends AstJSDocTagData { + tagName: AstIdentifier = undefined!; + comment: string | undefined = undefined; + commentArray: AstNodeArray | undefined = undefined; constraint: AstJSDocTypeExpression | undefined = undefined; typeParameters: AstNodeArray = undefined!; + static { + createDataInstanceMap[SyntaxKind.JSDocTemplateTag] = _ => new this(); + } } // dprint-ignore export class AstJSDocSeeTagData extends AstJSDocTagData { + tagName: AstIdentifier = undefined!; + comment: string | undefined = undefined; + commentArray: AstNodeArray | undefined = undefined; name: AstJSDocNameReference | undefined = undefined; + static { + createDataInstanceMap[SyntaxKind.JSDocSeeTag] = _ => new this(); + } } // dprint-ignore export class AstJSDocReturnTagData extends AstJSDocTagData { + tagName: AstIdentifier = undefined!; + comment: string | undefined = undefined; + commentArray: AstNodeArray | undefined = undefined; typeExpression: AstJSDocTypeExpression | undefined = undefined; + static { + createDataInstanceMap[SyntaxKind.JSDocReturnTag] = _ => new this(); + } } // dprint-ignore export class AstJSDocTypeTagData extends AstJSDocTagData { + tagName: AstIdentifier = undefined!; + comment: string | undefined = undefined; + commentArray: AstNodeArray | undefined = undefined; typeExpression: AstJSDocTypeExpression = undefined!; + static { + createDataInstanceMap[SyntaxKind.JSDocTypeTag] = _ => new this(); + } } // dprint-ignore export class AstJSDocTypedefTagData extends AstJSDocTagData { + tagName: AstIdentifier = undefined!; + comment: string | undefined = undefined; + commentArray: AstNodeArray | undefined = undefined; typeExpression: AstJSDocTypeExpression | AstJSDocTypeLiteral | undefined = undefined; fullName: AstJSDocNamespaceDeclaration | AstIdentifier | undefined = undefined; name: AstIdentifier | undefined = undefined; @@ -4241,10 +5123,16 @@ export class AstJSDocTypedefTagData extends AstJSDocTagData { /** @internal */ localSymbol: Symbol | undefined = undefined; // initialized by binder (Declaration) /** @internal */ locals: SymbolTable | undefined = undefined; /** @internal */ nextContainer: AstHasLocals | undefined = undefined; + static { + createDataInstanceMap[SyntaxKind.JSDocTypedefTag] = _ => new this(); + } } // dprint-ignore export class AstJSDocCallbackTagData extends AstJSDocTagData { + tagName: AstIdentifier = undefined!; + comment: string | undefined = undefined; + commentArray: AstNodeArray | undefined = undefined; fullName: AstJSDocNamespaceDeclaration | AstIdentifier | undefined = undefined; name: AstIdentifier | undefined = undefined; typeExpression: AstJSDocSignature = undefined!; @@ -4253,16 +5141,31 @@ export class AstJSDocCallbackTagData extends AstJSDocTagData { /** @internal */ localSymbol: Symbol | undefined = undefined; // initialized by binder (Declaration) /** @internal */ locals: SymbolTable | undefined = undefined; /** @internal */ nextContainer: AstHasLocals | undefined = undefined; + static { + createDataInstanceMap[SyntaxKind.JSDocCallbackTag] = _ => new this(); + } } // dprint-ignore export class AstJSDocOverloadTagData extends AstJSDocTagData { + tagName: AstIdentifier = undefined!; + comment: string | undefined = undefined; + commentArray: AstNodeArray | undefined = undefined; typeExpression: AstJSDocSignature = undefined!; + static { + createDataInstanceMap[SyntaxKind.JSDocOverloadTag] = _ => new this(); + } } // dprint-ignore export class AstJSDocThrowsTagData extends AstJSDocTagData { + tagName: AstIdentifier = undefined!; + comment: string | undefined = undefined; + commentArray: AstNodeArray | undefined = undefined; typeExpression: AstJSDocTypeExpression | undefined = undefined; + static { + createDataInstanceMap[SyntaxKind.JSDocThrowsTag] = _ => new this(); + } } // dprint-ignore @@ -4276,10 +5179,17 @@ export class AstJSDocSignatureData extends AstData { /** @internal */ localSymbol: Symbol | undefined = undefined; // initialized by binder (Declaration) /** @internal */ locals: SymbolTable | undefined = undefined; /** @internal */ nextContainer: AstHasLocals | undefined = undefined; + + static { + createDataInstanceMap[SyntaxKind.JSDocSignature] = _ => new this(); + } } // dprint-ignore export class AstJSDocPropertyTagData extends AstJSDocTagData { + tagName: AstIdentifier = undefined!; + comment: string | undefined = undefined; + commentArray: AstNodeArray | undefined = undefined; typeExpression: AstJSDocTypeExpression | undefined = undefined; name: AstEntityName = undefined!; /** Whether the property name came before the type -- non-standard for JSDoc, but Typescript-like */ @@ -4288,10 +5198,16 @@ export class AstJSDocPropertyTagData extends AstJSDocTagData { /** @internal */ symbol: Symbol = undefined!; // initialized by binder (Declaration) /** @internal */ localSymbol: Symbol | undefined = undefined; // initialized by binder (Declaration) + static { + createDataInstanceMap[SyntaxKind.JSDocPropertyTag] = _ => new this(); + } } // dprint-ignore export class AstJSDocParameterTagData extends AstJSDocTagData { + tagName: AstIdentifier = undefined!; + comment: string | undefined = undefined; + commentArray: AstNodeArray | undefined = undefined; typeExpression: AstJSDocTypeExpression | undefined = undefined; name: AstEntityName = undefined!; /** Whether the property name came before the type -- non-standard for JSDoc, but Typescript-like */ @@ -4300,6 +5216,9 @@ export class AstJSDocParameterTagData extends AstJSDocTagData { /** @internal */ symbol: Symbol = undefined!; // initialized by binder (Declaration) /** @internal */ localSymbol: Symbol | undefined = undefined; // initialized by binder (Declaration) + static { + createDataInstanceMap[SyntaxKind.JSDocParameterTag] = _ => new this(); + } } export type AstJSDocPropertyLikeTag = AstNodeOneOf; @@ -4312,18 +5231,34 @@ export class AstJSDocTypeLiteralData extends AstData { /** @internal */ symbol: Symbol = undefined!; // initialized by binder (Declaration) /** @internal */ localSymbol: Symbol | undefined = undefined; // initialized by binder (Declaration) + + static { + createDataInstanceMap[SyntaxKind.JSDocTypeLiteral] = _ => new this(); + } } // dprint-ignore export class AstJSDocSatisfiesTagData extends AstJSDocTagData { + tagName: AstIdentifier = undefined!; + comment: string | undefined = undefined; + commentArray: AstNodeArray | undefined = undefined; typeExpression: AstJSDocTypeExpression = undefined!; + static { + createDataInstanceMap[SyntaxKind.JSDocSatisfiesTag] = _ => new this(); + } } // dprint-ignore export class AstJSDocImportTagData extends AstJSDocTagData { + tagName: AstIdentifier = undefined!; + comment: string | undefined = undefined; + commentArray: AstNodeArray | undefined = undefined; importClause: AstImportClause | undefined = undefined; moduleSpecifier: AstExpression = undefined!; attributes: AstImportAttributes | undefined = undefined; + static { + createDataInstanceMap[SyntaxKind.JSDocImportTag] = _ => new this(); + } } // dprint-ignore @@ -4331,6 +5266,10 @@ export class AstSyntheticExpressionData extends AstData { isSpread = false; type: Type = undefined!; tupleNameSource: AstParameterDeclaration | AstNamedTupleMember | undefined = undefined; + + static { + createDataInstanceMap[SyntaxKind.SyntheticExpression] = _ => new this(); + } } // dprint-ignore @@ -4340,22 +5279,38 @@ export class AstBundleData extends AstData { /** @internal */ syntheticTypeReferences?: readonly FileReference[]; /** @internal */ syntheticLibReferences?: readonly FileReference[]; /** @internal */ hasNoDefaultLib?: boolean; + + static { + createDataInstanceMap[SyntaxKind.Bundle] = _ => new this(); + } } // dprint-ignore export class AstSyntaxListData extends AstData { /** @internal */ _children!: readonly Node[]; + + static { + createDataInstanceMap[SyntaxKind.SyntaxList] = _ => new this(); + } } // dprint-ignore export class AstNotEmittedStatementData extends AstData { /** @internal */ jsDoc: JSDocArray | undefined = undefined; // initialized by parser (JSDocContainer) + + static { + createDataInstanceMap[SyntaxKind.NotEmittedStatement] = _ => new this(); + } } // dprint-ignore export class AstNotEmittedTypeElementData extends AstData { /** @internal */ symbol: Symbol = undefined!; /** @internal */ localSymbol: Symbol | undefined = undefined; // initialized by binder (Declaration) + + static { + createDataInstanceMap[SyntaxKind.NotEmittedTypeElement] = _ => new this(); + } } // dprint-ignore @@ -4365,6 +5320,10 @@ export class AstPartiallyEmittedExpressionData extends AstData { /** @internal */ override computeTransformFlags(_: AstNode): TransformFlags { return propagateChildFlags(this.expression); } + + static { + createDataInstanceMap[SyntaxKind.PartiallyEmittedExpression] = _ => new this(); + } } // dprint-ignore @@ -4374,6 +5333,10 @@ export class AstCommaListExpressionData extends AstData { /** @internal */ override computeTransformFlags(_: AstNode): TransformFlags { return propagateChildrenFlags(this.elements); } + + static { + createDataInstanceMap[SyntaxKind.CommaListExpression] = _ => new this(); + } } /** @internal */ @@ -4386,6 +5349,10 @@ export class AstSyntheticReferenceExpressionData extends AstData { return propagateChildFlags(this.expression) | propagateChildFlags(this.thisArg); } + + static { + createDataInstanceMap[SyntaxKind.SyntheticReferenceExpression] = _ => new this(); + } } // dprint-ignore @@ -4560,14 +5527,21 @@ export class AstSourceFileData extends AstData { propagateChildFlags(this.endOfFileToken); } - override cloneNode(node: AstNode): AstNode { - if (this.redirectInfo) { - const clone = this.redirectInfo.redirectTarget.ast.shadow() as AstSourceFile; - this.copyProperties(clone.data); - clone.emitNode = undefined; - return clone; - } - return super.cloneNode(node); + static { + cloneNodeMap[SyntaxKind.SourceFile] = (node: AstNode) => { + Debug.assert(node.data instanceof this); + if (node.data.redirectInfo) { + const clone = node.data.redirectInfo.redirectTarget.ast.shadow() as AstSourceFile; + copyDataProperties(node, clone.data); + clone.emitNode = undefined; + return clone; + } + return cloneNodeCore(node); + }; + } + + static { + createDataInstanceMap[SyntaxKind.SourceFile] = _ => new this(); } } @@ -4899,7 +5873,7 @@ function propagateChildFlags(child: AstNode | undefined): TransformFlags { if (!child) return TransformFlags.None; const childFlags = child.transformFlags & ~getTransformFlagsSubtreeExclusions(child.kind); const name = astGetName(child); - return name && isAstPropertyName(name) ? propagatePropertyNameFlagsOfChild(name, childFlags) : childFlags; + return name && astIsPropertyName(name) ? propagatePropertyNameFlagsOfChild(name, childFlags) : childFlags; } function propagateChildrenFlags(children: AstNodeArray | undefined): TransformFlags { @@ -4919,14 +5893,32 @@ function getTransformFlagsOfTemplateLiteralLike(templateFlags: TokenFlags) { return transformFlags; } -/** @internal */ export type AstNamedDeclaration = AstNodeOneOf; +/** @internal */ +export type AstDynamicNamedDeclaration = AstNodeOneOf; + +/** @internal */ +export type AstDynamicNamedBinaryExpression = AstNodeOneOf; + /** @internal */ export type AstHasName = AstNodeOneOf; +/** @internal */ +export type AstHasExpression = AstNodeOneOf; + +/** @internal */ +export type AstHasInitializer = AstNodeOneOf; + +/** @internal */ +export type AstThisContainer = AstNodeOneOf; + +/** @internal */ +export type AstGetResult = T extends Base ? T["data"][K] : Base["data"][K] | undefined; + /** @internal */ export function astCanHaveName(node: AstNode): node is AstHasName { + Debug.type(node); // ensures `astCanHaveName` is up-to-date with `AstHasName`/`HasName` switch (node.kind) { case SyntaxKind.BindingElement: case SyntaxKind.ClassDeclaration: @@ -4973,8 +5965,10 @@ export function astCanHaveName(node: AstNode): node is AstHasName { case SyntaxKind.TypeParameter: case SyntaxKind.VariableDeclaration: return true; + default: + Debug.assertNeverTypeOnly(node); // ensures `astCanHaveName` is up-to-date with `AstHasName`/`HasName` + return false; } - return false; } /** @internal */ @@ -4983,10 +5977,10 @@ export function astHasName(node: AstNode): node is AstNodeOneOf(node: T): T extends AstHasName ? T["data"]["name"] : undefined; +export function astGetName(node: T): AstGetResult; export function astGetName(node: AstNode) { - Debug.type(node); - // NOTE: each branch is monomorphic + Debug.type(node); // ensures `astGetName` is up-to-date with `AstHasName`/`HasName` + // NOTE: each branch is duplicated to remain monomorphic switch (node.kind) { case SyntaxKind.BindingElement: return node.data.name; case SyntaxKind.ClassDeclaration: return node.data.name; @@ -5032,12 +6026,15 @@ export function astGetName(node: AstNode) { case SyntaxKind.TypeAliasDeclaration: return node.data.name; case SyntaxKind.TypeParameter: return node.data.name; case SyntaxKind.VariableDeclaration: return node.data.name; - default: return undefined; + default: + Debug.assertNeverTypeOnly(node); // ensures `astGetName` is up-to-date with `AstHasName`/`HasName` + return undefined; } } /** @internal */ export function astCanHaveJSDoc(node: AstNode): node is AstHasJSDoc { + Debug.type(node); // ensures `astCanHaveJSDoc` is up-to-date with `AstHasJSDoc`/`HasJSDoc` switch (node.kind) { case SyntaxKind.ArrowFunction: case SyntaxKind.BinaryExpression: @@ -5110,6 +6107,7 @@ export function astCanHaveJSDoc(node: AstNode): node is AstHasJSDoc { case SyntaxKind.NotEmittedStatement: return true; default: + Debug.assertNeverTypeOnly(node); // ensures `astCanHaveJSDoc` is up-to-date with `AstHasJSDoc`/`HasJSDoc` return false; } } @@ -5121,8 +6119,8 @@ export function astHasJSDoc(node: AstNode): node is AstNodeOneOf(node); + Debug.type(node); // ensures `astGetJSDoc` is up-to-date with `AstHasJSDoc`/`HasJSDoc` + // NOTE: each branch is duplicated to remain monomorphic switch (node.kind) { case SyntaxKind.ArrowFunction: return node.data.jsDoc; case SyntaxKind.BinaryExpression: return node.data.jsDoc; @@ -5193,226 +6191,1563 @@ export function astGetJSDoc(node: AstNode): JSDocArray | undefined { case SyntaxKind.ModuleBlock: return node.data.jsDoc; case SyntaxKind.MissingDeclaration: return node.data.jsDoc; case SyntaxKind.NotEmittedStatement: return node.data.jsDoc; - default: Debug.assertNever(node); + default: + Debug.assertNeverTypeOnly(node); // ensures `astGetJSDoc` is up-to-date with `AstHasJSDoc`/`HasJSDoc` + return undefined; } } /** @internal */ -export function astSetJSDoc(node: AstHasJSDoc, value: JSDocArray | undefined): void { - // each branch is monomorphic +export function astSetJSDoc(node: AstHasJSDoc, value: JSDocArray | undefined): JSDocArray | undefined { + // NOTE: each branch is duplicated to remain monomorphic switch (node.kind) { - case SyntaxKind.ArrowFunction: - node.data.jsDoc = value; - break; - case SyntaxKind.BinaryExpression: - node.data.jsDoc = value; - break; - case SyntaxKind.Block: - node.data.jsDoc = value; - break; - case SyntaxKind.BreakStatement: - node.data.jsDoc = value; - break; - case SyntaxKind.CallSignature: - node.data.jsDoc = value; - break; - case SyntaxKind.CaseClause: - node.data.jsDoc = value; - break; - case SyntaxKind.ClassDeclaration: - node.data.jsDoc = value; - break; - case SyntaxKind.ClassExpression: - node.data.jsDoc = value; - break; - case SyntaxKind.ClassStaticBlockDeclaration: - node.data.jsDoc = value; - break; - case SyntaxKind.Constructor: - node.data.jsDoc = value; - break; - case SyntaxKind.ConstructorType: - node.data.jsDoc = value; - break; - case SyntaxKind.ConstructSignature: - node.data.jsDoc = value; - break; - case SyntaxKind.ContinueStatement: - node.data.jsDoc = value; - break; - case SyntaxKind.DebuggerStatement: - node.data.jsDoc = value; - break; - case SyntaxKind.DoStatement: - node.data.jsDoc = value; - break; - case SyntaxKind.ElementAccessExpression: - node.data.jsDoc = value; - break; - case SyntaxKind.EmptyStatement: - node.data.jsDoc = value; - break; - case SyntaxKind.EndOfFileToken: - node.data.jsDoc = value; - break; - case SyntaxKind.EnumDeclaration: - node.data.jsDoc = value; - break; - case SyntaxKind.EnumMember: - node.data.jsDoc = value; - break; - case SyntaxKind.ExportAssignment: - node.data.jsDoc = value; - break; - case SyntaxKind.ExportDeclaration: - node.data.jsDoc = value; - break; - case SyntaxKind.ExportSpecifier: - node.data.jsDoc = value; - break; - case SyntaxKind.ExpressionStatement: - node.data.jsDoc = value; - break; - case SyntaxKind.ForInStatement: - node.data.jsDoc = value; - break; - case SyntaxKind.ForOfStatement: - node.data.jsDoc = value; - break; - case SyntaxKind.ForStatement: - node.data.jsDoc = value; - break; - case SyntaxKind.FunctionDeclaration: - node.data.jsDoc = value; - break; - case SyntaxKind.FunctionExpression: - node.data.jsDoc = value; - break; - case SyntaxKind.FunctionType: - node.data.jsDoc = value; - break; - case SyntaxKind.GetAccessor: - node.data.jsDoc = value; - break; - case SyntaxKind.Identifier: - node.data.jsDoc = value; - break; - case SyntaxKind.IfStatement: - node.data.jsDoc = value; - break; - case SyntaxKind.ImportDeclaration: - node.data.jsDoc = value; - break; - case SyntaxKind.ImportEqualsDeclaration: - node.data.jsDoc = value; - break; - case SyntaxKind.IndexSignature: - node.data.jsDoc = value; - break; - case SyntaxKind.InterfaceDeclaration: - node.data.jsDoc = value; - break; - case SyntaxKind.JSDocFunctionType: - node.data.jsDoc = value; - break; - case SyntaxKind.JSDocSignature: - node.data.jsDoc = value; - break; - case SyntaxKind.LabeledStatement: - node.data.jsDoc = value; - break; - case SyntaxKind.MethodDeclaration: - node.data.jsDoc = value; - break; - case SyntaxKind.MethodSignature: - node.data.jsDoc = value; - break; - case SyntaxKind.ModuleDeclaration: - node.data.jsDoc = value; - break; - case SyntaxKind.NamedTupleMember: - node.data.jsDoc = value; - break; - case SyntaxKind.NamespaceExportDeclaration: - node.data.jsDoc = value; - break; - case SyntaxKind.ObjectLiteralExpression: - node.data.jsDoc = value; - break; - case SyntaxKind.Parameter: - node.data.jsDoc = value; - break; - case SyntaxKind.ParenthesizedExpression: - node.data.jsDoc = value; - break; - case SyntaxKind.PropertyAccessExpression: - node.data.jsDoc = value; - break; - case SyntaxKind.PropertyAssignment: - node.data.jsDoc = value; - break; - case SyntaxKind.PropertyDeclaration: - node.data.jsDoc = value; - break; - case SyntaxKind.PropertySignature: - node.data.jsDoc = value; - break; - case SyntaxKind.ReturnStatement: - node.data.jsDoc = value; - break; - case SyntaxKind.SemicolonClassElement: - node.data.jsDoc = value; - break; - case SyntaxKind.SetAccessor: - node.data.jsDoc = value; - break; - case SyntaxKind.ShorthandPropertyAssignment: - node.data.jsDoc = value; - break; - case SyntaxKind.SpreadAssignment: - node.data.jsDoc = value; - break; - case SyntaxKind.SwitchStatement: - node.data.jsDoc = value; - break; - case SyntaxKind.ThrowStatement: - node.data.jsDoc = value; - break; - case SyntaxKind.TryStatement: - node.data.jsDoc = value; - break; - case SyntaxKind.TypeAliasDeclaration: - node.data.jsDoc = value; - break; - case SyntaxKind.TypeParameter: - node.data.jsDoc = value; - break; - case SyntaxKind.VariableDeclaration: - node.data.jsDoc = value; - break; - case SyntaxKind.VariableStatement: - node.data.jsDoc = value; - break; - case SyntaxKind.WhileStatement: - node.data.jsDoc = value; - break; - case SyntaxKind.WithStatement: - node.data.jsDoc = value; - break; - case SyntaxKind.ModuleBlock: - node.data.jsDoc = value; - break; - case SyntaxKind.MissingDeclaration: - node.data.jsDoc = value; - break; - case SyntaxKind.NotEmittedStatement: - node.data.jsDoc = value; - break; - default: Debug.assertNever(node); + case SyntaxKind.ArrowFunction: return node.data.jsDoc = value; + case SyntaxKind.BinaryExpression: return node.data.jsDoc = value; + case SyntaxKind.Block: return node.data.jsDoc = value; + case SyntaxKind.BreakStatement: return node.data.jsDoc = value; + case SyntaxKind.CallSignature: return node.data.jsDoc = value; + case SyntaxKind.CaseClause: return node.data.jsDoc = value; + case SyntaxKind.ClassDeclaration: return node.data.jsDoc = value; + case SyntaxKind.ClassExpression: return node.data.jsDoc = value; + case SyntaxKind.ClassStaticBlockDeclaration: return node.data.jsDoc = value; + case SyntaxKind.Constructor: return node.data.jsDoc = value; + case SyntaxKind.ConstructorType: return node.data.jsDoc = value; + case SyntaxKind.ConstructSignature: return node.data.jsDoc = value; + case SyntaxKind.ContinueStatement: return node.data.jsDoc = value; + case SyntaxKind.DebuggerStatement: return node.data.jsDoc = value; + case SyntaxKind.DoStatement: return node.data.jsDoc = value; + case SyntaxKind.ElementAccessExpression: return node.data.jsDoc = value; + case SyntaxKind.EmptyStatement: return node.data.jsDoc = value; + case SyntaxKind.EndOfFileToken: return node.data.jsDoc = value; + case SyntaxKind.EnumDeclaration: return node.data.jsDoc = value; + case SyntaxKind.EnumMember: return node.data.jsDoc = value; + case SyntaxKind.ExportAssignment: return node.data.jsDoc = value; + case SyntaxKind.ExportDeclaration: return node.data.jsDoc = value; + case SyntaxKind.ExportSpecifier: return node.data.jsDoc = value; + case SyntaxKind.ExpressionStatement: return node.data.jsDoc = value; + case SyntaxKind.ForInStatement: return node.data.jsDoc = value; + case SyntaxKind.ForOfStatement: return node.data.jsDoc = value; + case SyntaxKind.ForStatement: return node.data.jsDoc = value; + case SyntaxKind.FunctionDeclaration: return node.data.jsDoc = value; + case SyntaxKind.FunctionExpression: return node.data.jsDoc = value; + case SyntaxKind.FunctionType: return node.data.jsDoc = value; + case SyntaxKind.GetAccessor: return node.data.jsDoc = value; + case SyntaxKind.Identifier: return node.data.jsDoc = value; + case SyntaxKind.IfStatement: return node.data.jsDoc = value; + case SyntaxKind.ImportDeclaration: return node.data.jsDoc = value; + case SyntaxKind.ImportEqualsDeclaration: return node.data.jsDoc = value; + case SyntaxKind.IndexSignature: return node.data.jsDoc = value; + case SyntaxKind.InterfaceDeclaration: return node.data.jsDoc = value; + case SyntaxKind.JSDocFunctionType: return node.data.jsDoc = value; + case SyntaxKind.JSDocSignature: return node.data.jsDoc = value; + case SyntaxKind.LabeledStatement: return node.data.jsDoc = value; + case SyntaxKind.MethodDeclaration: return node.data.jsDoc = value; + case SyntaxKind.MethodSignature: return node.data.jsDoc = value; + case SyntaxKind.ModuleDeclaration: return node.data.jsDoc = value; + case SyntaxKind.NamedTupleMember: return node.data.jsDoc = value; + case SyntaxKind.NamespaceExportDeclaration: return node.data.jsDoc = value; + case SyntaxKind.ObjectLiteralExpression: return node.data.jsDoc = value; + case SyntaxKind.Parameter: return node.data.jsDoc = value; + case SyntaxKind.ParenthesizedExpression: return node.data.jsDoc = value; + case SyntaxKind.PropertyAccessExpression: return node.data.jsDoc = value; + case SyntaxKind.PropertyAssignment: return node.data.jsDoc = value; + case SyntaxKind.PropertyDeclaration: return node.data.jsDoc = value; + case SyntaxKind.PropertySignature: return node.data.jsDoc = value; + case SyntaxKind.ReturnStatement: return node.data.jsDoc = value; + case SyntaxKind.SemicolonClassElement: return node.data.jsDoc = value; + case SyntaxKind.SetAccessor: return node.data.jsDoc = value; + case SyntaxKind.ShorthandPropertyAssignment: return node.data.jsDoc = value; + case SyntaxKind.SpreadAssignment: return node.data.jsDoc = value; + case SyntaxKind.SwitchStatement: return node.data.jsDoc = value; + case SyntaxKind.ThrowStatement: return node.data.jsDoc = value; + case SyntaxKind.TryStatement: return node.data.jsDoc = value; + case SyntaxKind.TypeAliasDeclaration: return node.data.jsDoc = value; + case SyntaxKind.TypeParameter: return node.data.jsDoc = value; + case SyntaxKind.VariableDeclaration: return node.data.jsDoc = value; + case SyntaxKind.VariableStatement: return node.data.jsDoc = value; + case SyntaxKind.WhileStatement: return node.data.jsDoc = value; + case SyntaxKind.WithStatement: return node.data.jsDoc = value; + case SyntaxKind.ModuleBlock: return node.data.jsDoc = value; + case SyntaxKind.MissingDeclaration: return node.data.jsDoc = value; + case SyntaxKind.NotEmittedStatement: return node.data.jsDoc = value; + default: + Debug.assertNever(node); // ensures `astSetJSDoc` is up-to-date with `AstHasJSDoc`/`HasJSDoc` } } -// NOTE: each branch is monomorphic +/** @internal */ +export function astCanHaveExpression(node: AstNode): node is AstHasExpression { + Debug.type(node); // ensures `astCanHaveExpression` is up-to-date with `AstHasExpression`/`HasExpression` + switch (node.kind) { + case SyntaxKind.ComputedPropertyName: + case SyntaxKind.TypeParameter: + case SyntaxKind.Decorator: + case SyntaxKind.PropertyAccessExpression: + case SyntaxKind.ElementAccessExpression: + case SyntaxKind.CallExpression: + case SyntaxKind.NewExpression: + case SyntaxKind.TypeAssertionExpression: + case SyntaxKind.ParenthesizedExpression: + case SyntaxKind.DeleteExpression: + case SyntaxKind.TypeOfExpression: + case SyntaxKind.VoidExpression: + case SyntaxKind.AwaitExpression: + case SyntaxKind.ForInStatement: + case SyntaxKind.ForOfStatement: + case SyntaxKind.ExpressionStatement: + case SyntaxKind.IfStatement: + case SyntaxKind.DoStatement: + case SyntaxKind.WhileStatement: + case SyntaxKind.YieldExpression: + case SyntaxKind.SpreadElement: + case SyntaxKind.ExpressionWithTypeArguments: + case SyntaxKind.AsExpression: + case SyntaxKind.NonNullExpression: + case SyntaxKind.SatisfiesExpression: + case SyntaxKind.TemplateSpan: + case SyntaxKind.ReturnStatement: + case SyntaxKind.WithStatement: + case SyntaxKind.SwitchStatement: + case SyntaxKind.ThrowStatement: + case SyntaxKind.ExportAssignment: + case SyntaxKind.ExternalModuleReference: + case SyntaxKind.JsxSpreadAttribute: + case SyntaxKind.JsxExpression: + case SyntaxKind.CaseClause: + case SyntaxKind.SpreadAssignment: + case SyntaxKind.PartiallyEmittedExpression: + case SyntaxKind.SyntheticReferenceExpression: + return true; + default: + Debug.assertNeverTypeOnly(node); // ensures `astCanHaveExpression` is up-to-date with `AstHasExpression`/`HasExpression` + return false; + } +} + +/** @internal */ +export function astGetExpression(node: T): AstGetResult; +export function astGetExpression(node: AstNode) { + Debug.type(node); // ensures `astGetExpression` is up-to-date with `AstHasExpression`/`HasExpression` + // NOTE: each branch is duplicated to remain monomorphic + switch (node.kind) { + case SyntaxKind.ComputedPropertyName: return node.data.expression; + case SyntaxKind.TypeParameter: return node.data.expression; + case SyntaxKind.Decorator: return node.data.expression; + case SyntaxKind.PropertyAccessExpression: return node.data.expression; + case SyntaxKind.ElementAccessExpression: return node.data.expression; + case SyntaxKind.CallExpression: return node.data.expression; + case SyntaxKind.NewExpression: return node.data.expression; + case SyntaxKind.TypeAssertionExpression: return node.data.expression; + case SyntaxKind.ParenthesizedExpression: return node.data.expression; + case SyntaxKind.DeleteExpression: return node.data.expression; + case SyntaxKind.TypeOfExpression: return node.data.expression; + case SyntaxKind.VoidExpression: return node.data.expression; + case SyntaxKind.AwaitExpression: return node.data.expression; + case SyntaxKind.ForInStatement: return node.data.expression; + case SyntaxKind.ForOfStatement: return node.data.expression; + case SyntaxKind.ExpressionStatement: return node.data.expression; + case SyntaxKind.IfStatement: return node.data.expression; + case SyntaxKind.DoStatement: return node.data.expression; + case SyntaxKind.WhileStatement: return node.data.expression; + case SyntaxKind.YieldExpression: return node.data.expression; + case SyntaxKind.SpreadElement: return node.data.expression; + case SyntaxKind.ExpressionWithTypeArguments: return node.data.expression; + case SyntaxKind.AsExpression: return node.data.expression; + case SyntaxKind.NonNullExpression: return node.data.expression; + case SyntaxKind.SatisfiesExpression: return node.data.expression; + case SyntaxKind.TemplateSpan: return node.data.expression; + case SyntaxKind.ReturnStatement: return node.data.expression; + case SyntaxKind.WithStatement: return node.data.expression; + case SyntaxKind.SwitchStatement: return node.data.expression; + case SyntaxKind.ThrowStatement: return node.data.expression; + case SyntaxKind.ExportAssignment: return node.data.expression; + case SyntaxKind.ExternalModuleReference: return node.data.expression; + case SyntaxKind.JsxSpreadAttribute: return node.data.expression; + case SyntaxKind.JsxExpression: return node.data.expression; + case SyntaxKind.CaseClause: return node.data.expression; + case SyntaxKind.SpreadAssignment: return node.data.expression; + case SyntaxKind.PartiallyEmittedExpression: return node.data.expression; + case SyntaxKind.SyntheticReferenceExpression: return node.data.expression; + default: + Debug.assertNeverTypeOnly(node); // ensures `astGetExpression` is up-to-date with `AstHasExpression`/`HasExpression` + return undefined; + } +} + +/** @internal */ +export function astCanHaveFlowNode(node: AstNode): node is AstHasFlowNode { + Debug.type(node); // ensures `astCanHaveFlowNode` is up-to-date with `AstHasFlowNode`/`HasFlowNode` + switch (node.kind) { + case SyntaxKind.VariableStatement: + case SyntaxKind.ExpressionStatement: + case SyntaxKind.IfStatement: + case SyntaxKind.DoStatement: + case SyntaxKind.WhileStatement: + case SyntaxKind.ForStatement: + case SyntaxKind.ForInStatement: + case SyntaxKind.ForOfStatement: + case SyntaxKind.ContinueStatement: + case SyntaxKind.BreakStatement: + case SyntaxKind.ReturnStatement: + case SyntaxKind.WithStatement: + case SyntaxKind.SwitchStatement: + case SyntaxKind.LabeledStatement: + case SyntaxKind.ThrowStatement: + case SyntaxKind.TryStatement: + case SyntaxKind.DebuggerStatement: + 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: + Debug.assertNeverTypeOnly(node); // ensures `astCanHaveFlowNode` is up-to-date with `AstHasFlowNode`/`HasFlowNode` + return false; + } +} + +/** @internal */ +export function astGetFlowNode(node: AstNode): FlowNode | undefined { + Debug.type(node); // ensures `astGetFlowNode` is up-to-date with `AstHasFlowNode`/`HasFlowNode` + // NOTE: each branch is duplicated to remain monomorphic + switch (node.kind) { + case SyntaxKind.VariableStatement: return node.data.flowNode; + case SyntaxKind.ExpressionStatement: return node.data.flowNode; + case SyntaxKind.IfStatement: return node.data.flowNode; + case SyntaxKind.DoStatement: return node.data.flowNode; + case SyntaxKind.WhileStatement: return node.data.flowNode; + case SyntaxKind.ForStatement: return node.data.flowNode; + case SyntaxKind.ForInStatement: return node.data.flowNode; + case SyntaxKind.ForOfStatement: return node.data.flowNode; + case SyntaxKind.ContinueStatement: return node.data.flowNode; + case SyntaxKind.BreakStatement: return node.data.flowNode; + case SyntaxKind.ReturnStatement: return node.data.flowNode; + case SyntaxKind.WithStatement: return node.data.flowNode; + case SyntaxKind.SwitchStatement: return node.data.flowNode; + case SyntaxKind.LabeledStatement: return node.data.flowNode; + case SyntaxKind.ThrowStatement: return node.data.flowNode; + case SyntaxKind.TryStatement: return node.data.flowNode; + case SyntaxKind.DebuggerStatement: return node.data.flowNode; + case SyntaxKind.Identifier: return node.data.flowNode; + case SyntaxKind.ThisKeyword: return node.data.flowNode; + case SyntaxKind.SuperKeyword: return node.data.flowNode; + case SyntaxKind.QualifiedName: return node.data.flowNode; + case SyntaxKind.MetaProperty: return node.data.flowNode; + case SyntaxKind.ElementAccessExpression: return node.data.flowNode; + case SyntaxKind.PropertyAccessExpression: return node.data.flowNode; + case SyntaxKind.BindingElement: return node.data.flowNode; + case SyntaxKind.FunctionExpression: return node.data.flowNode; + case SyntaxKind.ArrowFunction: return node.data.flowNode; + case SyntaxKind.MethodDeclaration: return node.data.flowNode; + case SyntaxKind.GetAccessor: return node.data.flowNode; + case SyntaxKind.SetAccessor: return node.data.flowNode; + default: + Debug.assertNeverTypeOnly(node); // ensures `astGetFlowNode` is up-to-date with `AstHasFlowNode`/`HasFlowNode` + return undefined; + } +} + +/** @internal */ +export function astSetFlowNode(node: AstHasFlowNode, value: FlowNode | undefined): FlowNode | undefined { + // NOTE: each branch is duplicated to remain monomorphic + switch (node.kind) { + case SyntaxKind.VariableStatement: return node.data.flowNode = value; + case SyntaxKind.ExpressionStatement: return node.data.flowNode = value; + case SyntaxKind.IfStatement: return node.data.flowNode = value; + case SyntaxKind.DoStatement: return node.data.flowNode = value; + case SyntaxKind.WhileStatement: return node.data.flowNode = value; + case SyntaxKind.ForStatement: return node.data.flowNode = value; + case SyntaxKind.ForInStatement: return node.data.flowNode = value; + case SyntaxKind.ForOfStatement: return node.data.flowNode = value; + case SyntaxKind.ContinueStatement: return node.data.flowNode = value; + case SyntaxKind.BreakStatement: return node.data.flowNode = value; + case SyntaxKind.ReturnStatement: return node.data.flowNode = value; + case SyntaxKind.WithStatement: return node.data.flowNode = value; + case SyntaxKind.SwitchStatement: return node.data.flowNode = value; + case SyntaxKind.LabeledStatement: return node.data.flowNode = value; + case SyntaxKind.ThrowStatement: return node.data.flowNode = value; + case SyntaxKind.TryStatement: return node.data.flowNode = value; + case SyntaxKind.DebuggerStatement: return node.data.flowNode = value; + case SyntaxKind.Identifier: return node.data.flowNode = value; + case SyntaxKind.ThisKeyword: return node.data.flowNode = value; + case SyntaxKind.SuperKeyword: return node.data.flowNode = value; + case SyntaxKind.QualifiedName: return node.data.flowNode = value; + case SyntaxKind.MetaProperty: return node.data.flowNode = value; + case SyntaxKind.ElementAccessExpression: return node.data.flowNode = value; + case SyntaxKind.PropertyAccessExpression: return node.data.flowNode = value; + case SyntaxKind.BindingElement: return node.data.flowNode = value; + case SyntaxKind.FunctionExpression: return node.data.flowNode = value; + case SyntaxKind.ArrowFunction: return node.data.flowNode = value; + case SyntaxKind.MethodDeclaration: return node.data.flowNode = value; + case SyntaxKind.GetAccessor: return node.data.flowNode = value; + case SyntaxKind.SetAccessor: return node.data.flowNode = value; + default: + return Debug.assertNever(node); // ensures `astSetFlowNode` is up-to-date with `AstHasFlowNode`/`HasFlowNode` + } +} + +/** @internal */ +export function astGetEndFlowNode(node: AstNode): FlowNode | undefined { + Debug.type(node); // ensures `astGetEndFlowNode` is up-to-date with `AstHasEndFlowNode`/`HasEndFlowNode` + // NOTE: each branch is duplicated to remain monomorphic + switch (node.kind) { + case SyntaxKind.MethodDeclaration: return node.data.endFlowNode; + case SyntaxKind.ClassStaticBlockDeclaration: return node.data.endFlowNode; + case SyntaxKind.Constructor: return node.data.endFlowNode; + case SyntaxKind.GetAccessor: return node.data.endFlowNode; + case SyntaxKind.SetAccessor: return node.data.endFlowNode; + case SyntaxKind.FunctionExpression: return node.data.endFlowNode; + case SyntaxKind.ArrowFunction: return node.data.endFlowNode; + case SyntaxKind.FunctionDeclaration: return node.data.endFlowNode; + case SyntaxKind.SourceFile: return node.data.endFlowNode; + default: + Debug.assertNeverTypeOnly(node); // ensures `astGetEndFlowNode` is up-to-date with `AstHasEndFlowNode`/`HasEndFlowNode` + return undefined; + } +} + +/** @internal */ +export function astSetEndFlowNode(node: AstHasEndFlowNode, value: FlowNode | undefined): FlowNode | undefined { + // NOTE: each branch is duplicated to remain monomorphic + switch (node.kind) { + case SyntaxKind.MethodDeclaration: return node.data.endFlowNode = value; + case SyntaxKind.ClassStaticBlockDeclaration: return node.data.endFlowNode = value; + case SyntaxKind.Constructor: return node.data.endFlowNode = value; + case SyntaxKind.GetAccessor: return node.data.endFlowNode = value; + case SyntaxKind.SetAccessor: return node.data.endFlowNode = value; + case SyntaxKind.FunctionExpression: return node.data.endFlowNode = value; + case SyntaxKind.ArrowFunction: return node.data.endFlowNode = value; + case SyntaxKind.FunctionDeclaration: return node.data.endFlowNode = value; + case SyntaxKind.SourceFile: return node.data.endFlowNode = value; + default: + return Debug.assertNever(node); // ensures `astSetEndFlowNode` is up-to-date with `AstHasEndFlowNode`/`HasEndFlowNode` + } +} + +/** @internal */ +export function astCanHaveInitializer(node: AstNode): node is AstHasInitializer { + Debug.type(node); // ensures `astCanHaveInitializer` is up-to-date with `AstHasInitializer`/`HasInitializer` + switch (node.kind) { + case SyntaxKind.Parameter: + case SyntaxKind.PropertyDeclaration: + case SyntaxKind.BindingElement: + case SyntaxKind.ForStatement: + case SyntaxKind.ForInStatement: + case SyntaxKind.ForOfStatement: + case SyntaxKind.VariableDeclaration: + case SyntaxKind.JsxAttribute: + case SyntaxKind.PropertyAssignment: + case SyntaxKind.PropertySignature: + case SyntaxKind.EnumMember: + return true; + default: + Debug.assertNeverTypeOnly(node); // ensures `astCanHaveInitializer` is up-to-date with `AstHasInitializer`/`HasInitializer` + return false; + } +} + +/** @internal */ +export function astGetInitializer(node: T): AstGetResult; +export function astGetInitializer(node: AstNode) { + Debug.type(node); // ensures `astGetInitializer` is up-to-date with `AstHasInitializer`/`HasInitializer` + // NOTE: each branch is duplicated to remain monomorphic + switch (node.kind) { + case SyntaxKind.Parameter: return node.data.initializer; + case SyntaxKind.PropertyDeclaration: return node.data.initializer; + case SyntaxKind.BindingElement: return node.data.initializer; + case SyntaxKind.ForStatement: return node.data.initializer; + case SyntaxKind.ForInStatement: return node.data.initializer; + case SyntaxKind.ForOfStatement: return node.data.initializer; + case SyntaxKind.VariableDeclaration: return node.data.initializer; + case SyntaxKind.JsxAttribute: return node.data.initializer; + case SyntaxKind.PropertyAssignment: return node.data.initializer; + case SyntaxKind.PropertySignature: return node.data.initializer; + case SyntaxKind.EnumMember: return node.data.initializer; + default: + Debug.assertNeverTypeOnly(node); // ensures `astGetInitializer` is up-to-date with `AstHasInitializer`/`HasInitializer` + return undefined; + } +} + +/** @internal */ +export function astCanHaveModifiers(node: AstNode): node is AstHasModifiers { + Debug.type(node); // ensures `astCanHaveModifiers` is up-to-date with `AstHasModifiers`/`HasModifiers` + switch (node.kind) { + case SyntaxKind.TypeParameter: + case SyntaxKind.Parameter: + case SyntaxKind.PropertySignature: + case SyntaxKind.PropertyDeclaration: + case SyntaxKind.MethodSignature: + case SyntaxKind.MethodDeclaration: + case SyntaxKind.Constructor: + case SyntaxKind.GetAccessor: + case SyntaxKind.SetAccessor: + case SyntaxKind.IndexSignature: + case SyntaxKind.ConstructorType: + case SyntaxKind.FunctionExpression: + case SyntaxKind.ArrowFunction: + case SyntaxKind.ClassExpression: + case SyntaxKind.VariableStatement: + case SyntaxKind.FunctionDeclaration: + case SyntaxKind.ClassDeclaration: + case SyntaxKind.InterfaceDeclaration: + case SyntaxKind.TypeAliasDeclaration: + case SyntaxKind.EnumDeclaration: + case SyntaxKind.ModuleDeclaration: + case SyntaxKind.ImportEqualsDeclaration: + case SyntaxKind.ImportDeclaration: + case SyntaxKind.ExportAssignment: + case SyntaxKind.ExportDeclaration: + return true; + default: + Debug.assertNeverTypeOnly(node); // ensures `astCanHaveModifiers` is up-to-date with `AstHasModifiers`/`HasModifiers` + return false; + } +} + +/** @internal */ +export function astGetModifiers(node: T): AstGetResult; +export function astGetModifiers(node: AstNode) { + Debug.type(node); // ensures `astGetModifiers` is up-to-date with `AstHasModifiers`/`HasModifiers` + // NOTE: each branch is duplicated to remain monomorphic + switch (node.kind) { + case SyntaxKind.TypeParameter: return node.data.modifiers; + case SyntaxKind.Parameter: return node.data.modifiers; + case SyntaxKind.PropertySignature: return node.data.modifiers; + case SyntaxKind.PropertyDeclaration: return node.data.modifiers; + case SyntaxKind.MethodSignature: return node.data.modifiers; + case SyntaxKind.MethodDeclaration: return node.data.modifiers; + case SyntaxKind.Constructor: return node.data.modifiers; + case SyntaxKind.GetAccessor: return node.data.modifiers; + case SyntaxKind.SetAccessor: return node.data.modifiers; + case SyntaxKind.IndexSignature: return node.data.modifiers; + case SyntaxKind.ConstructorType: return node.data.modifiers; + case SyntaxKind.FunctionExpression: return node.data.modifiers; + case SyntaxKind.ArrowFunction: return node.data.modifiers; + case SyntaxKind.ClassExpression: return node.data.modifiers; + case SyntaxKind.VariableStatement: return node.data.modifiers; + case SyntaxKind.FunctionDeclaration: return node.data.modifiers; + case SyntaxKind.ClassDeclaration: return node.data.modifiers; + case SyntaxKind.InterfaceDeclaration: return node.data.modifiers; + case SyntaxKind.TypeAliasDeclaration: return node.data.modifiers; + case SyntaxKind.EnumDeclaration: return node.data.modifiers; + case SyntaxKind.ModuleDeclaration: return node.data.modifiers; + case SyntaxKind.ImportEqualsDeclaration: return node.data.modifiers; + case SyntaxKind.ImportDeclaration: return node.data.modifiers; + case SyntaxKind.ExportAssignment: return node.data.modifiers; + case SyntaxKind.ExportDeclaration: return node.data.modifiers; + case SyntaxKind.MissingDeclaration: return node.data.modifiers; + case SyntaxKind.ClassStaticBlockDeclaration: return node.data.modifiers; + case SyntaxKind.NamespaceExportDeclaration: return node.data.modifiers; + case SyntaxKind.PropertyAssignment: return node.data.modifiers; + case SyntaxKind.ShorthandPropertyAssignment: return node.data.modifiers; + default: + Debug.assertNeverTypeOnly(node); // ensures `astGetModifiers` is up-to-date with `AstHasModifiers`/`HasModifiers` + return undefined; + } +} + +/** @internal */ +export function astCanHaveDecorators(node: AstNode): node is AstHasDecorators { + Debug.type(node); // ensures `astCanHaveDecorators` is up-to-date with `AstHasDecorators`/`HasDecorators` + switch (node.kind) { + case SyntaxKind.Parameter: + case SyntaxKind.PropertyDeclaration: + case SyntaxKind.MethodDeclaration: + case SyntaxKind.GetAccessor: + case SyntaxKind.SetAccessor: + case SyntaxKind.ClassExpression: + case SyntaxKind.ClassDeclaration: + return true; + default: + Debug.assertNeverTypeOnly(node); // ensures `astCanHaveDecorators` is up-to-date with `AstHasDecorators`/`HasDecorators` + return false; + } +} + +/** @internal */ +export function astGetRawText(node: AstNode): string | undefined { + Debug.type(node); // ensures `astGetRawText` is up-to-date with `AstTemplateLiteralToken`/`TemplateLiteralToken` + // NOTE: each branch is duplicated to remain monomorphic + switch (node.kind) { + case SyntaxKind.NoSubstitutionTemplateLiteral: return node.data.rawText; + case SyntaxKind.TemplateHead: return node.data.rawText; + case SyntaxKind.TemplateMiddle: return node.data.rawText; + case SyntaxKind.TemplateTail: return node.data.rawText; + default: + Debug.assertNeverTypeOnly(node); // ensures `astGetRawText` is up-to-date with `AstTemplateLiteralToken`/`TemplateLiteralToken` + return undefined; + } +} + +/** @internal */ +export function astGetText(node: T): AstGetResult; +export function astGetText(node: AstNode): string | undefined { + Debug.type(node); // ensures `astGetText` is up-to-date with `AstHasText`/`HasText` + // NOTE: each branch is duplicated to remain monomorphic + switch (node.kind) { + case SyntaxKind.NumericLiteral: return node.data.text; + case SyntaxKind.BigIntLiteral: return node.data.text; + case SyntaxKind.StringLiteral: return node.data.text; + case SyntaxKind.RegularExpressionLiteral: return node.data.text; + case SyntaxKind.NoSubstitutionTemplateLiteral: return node.data.text; + case SyntaxKind.TemplateHead: return node.data.text; + case SyntaxKind.TemplateMiddle: return node.data.text; + case SyntaxKind.TemplateTail: return node.data.text; + case SyntaxKind.JsxText: return node.data.text; + case SyntaxKind.JSDocText: return node.data.text; + case SyntaxKind.JSDocLink: return node.data.text; + case SyntaxKind.JSDocLinkCode: return node.data.text; + case SyntaxKind.JSDocLinkPlain: return node.data.text; + case SyntaxKind.SourceFile: return node.data.text; + default: + Debug.assertNeverTypeOnly(node); // ensures `astGetText` is up-to-date with `AstHasText`/`HasText` + return undefined; + } +} + +/** @internal */ +export function astCanHaveSymbol(node: AstNode): node is AstHasSymbol { + Debug.type(node); // ensures `astCanHaveSymbol` is up-to-date with `AstHasSymbol`/`HasSymbol` + switch (node.kind) { + case SyntaxKind.NumericLiteral: + case SyntaxKind.StringLiteral: + case SyntaxKind.NoSubstitutionTemplateLiteral: + case SyntaxKind.Identifier: + case SyntaxKind.TypeParameter: + case SyntaxKind.Parameter: + case SyntaxKind.PropertySignature: + case SyntaxKind.PropertyDeclaration: + case SyntaxKind.MethodSignature: + case SyntaxKind.MethodDeclaration: + case SyntaxKind.ClassStaticBlockDeclaration: + case SyntaxKind.Constructor: + case SyntaxKind.GetAccessor: + case SyntaxKind.SetAccessor: + case SyntaxKind.CallSignature: + case SyntaxKind.ConstructSignature: + case SyntaxKind.IndexSignature: + case SyntaxKind.FunctionType: + case SyntaxKind.ConstructorType: + case SyntaxKind.TypeLiteral: + case SyntaxKind.MappedType: + case SyntaxKind.NamedTupleMember: + case SyntaxKind.BindingElement: + case SyntaxKind.ObjectLiteralExpression: + case SyntaxKind.PropertyAccessExpression: + case SyntaxKind.ElementAccessExpression: + case SyntaxKind.CallExpression: + case SyntaxKind.NewExpression: + case SyntaxKind.FunctionExpression: + case SyntaxKind.ArrowFunction: + case SyntaxKind.BinaryExpression: + case SyntaxKind.ClassExpression: + case SyntaxKind.VariableDeclaration: + case SyntaxKind.FunctionDeclaration: + case SyntaxKind.ClassDeclaration: + case SyntaxKind.InterfaceDeclaration: + case SyntaxKind.TypeAliasDeclaration: + case SyntaxKind.EnumDeclaration: + case SyntaxKind.ModuleDeclaration: + case SyntaxKind.NamespaceExportDeclaration: + case SyntaxKind.ImportEqualsDeclaration: + case SyntaxKind.ImportDeclaration: + case SyntaxKind.ImportClause: + case SyntaxKind.NamespaceImport: + case SyntaxKind.ImportSpecifier: + case SyntaxKind.ExportAssignment: + case SyntaxKind.ExportDeclaration: + case SyntaxKind.NamespaceExport: + case SyntaxKind.ExportSpecifier: + case SyntaxKind.MissingDeclaration: + case SyntaxKind.JsxAttribute: + case SyntaxKind.JsxAttributes: + case SyntaxKind.PropertyAssignment: + case SyntaxKind.ShorthandPropertyAssignment: + case SyntaxKind.SpreadAssignment: + case SyntaxKind.EnumMember: + case SyntaxKind.SourceFile: + case SyntaxKind.JSDocFunctionType: + case SyntaxKind.JSDocTypeLiteral: + case SyntaxKind.JSDocSignature: + case SyntaxKind.JSDocCallbackTag: + case SyntaxKind.JSDocEnumTag: + case SyntaxKind.JSDocParameterTag: + case SyntaxKind.JSDocTypedefTag: + case SyntaxKind.JSDocPropertyTag: + case SyntaxKind.NotEmittedTypeElement: + return true; + default: + Debug.assertNeverTypeOnly(node); // ensures `astCanHaveSymbol` is up-to-date with `AstHasSymbol`/`HasSymbol` + return false; + } +} + +/** @internal */ +export function astGetSymbol(node: T): T extends AstHasSymbol ? Symbol : Symbol | undefined; +export function astGetSymbol(node: T) { + Debug.type(node); // ensures `astGetSymbol` is up-to-date with `AstHasSymbol`/`HasSymbol` + // NOTE: each branch is duplicated to remain monomorphic + switch (node.kind) { + case SyntaxKind.NumericLiteral: return node.data.symbol; + case SyntaxKind.StringLiteral: return node.data.symbol; + case SyntaxKind.NoSubstitutionTemplateLiteral: return node.data.symbol; + case SyntaxKind.Identifier: return node.data.symbol; + case SyntaxKind.TypeParameter: return node.data.symbol; + case SyntaxKind.Parameter: return node.data.symbol; + case SyntaxKind.PropertySignature: return node.data.symbol; + case SyntaxKind.PropertyDeclaration: return node.data.symbol; + case SyntaxKind.MethodSignature: return node.data.symbol; + case SyntaxKind.MethodDeclaration: return node.data.symbol; + case SyntaxKind.ClassStaticBlockDeclaration: return node.data.symbol; + case SyntaxKind.Constructor: return node.data.symbol; + case SyntaxKind.GetAccessor: return node.data.symbol; + case SyntaxKind.SetAccessor: return node.data.symbol; + case SyntaxKind.CallSignature: return node.data.symbol; + case SyntaxKind.ConstructSignature: return node.data.symbol; + case SyntaxKind.IndexSignature: return node.data.symbol; + case SyntaxKind.FunctionType: return node.data.symbol; + case SyntaxKind.ConstructorType: return node.data.symbol; + case SyntaxKind.TypeLiteral: return node.data.symbol; + case SyntaxKind.MappedType: return node.data.symbol; + case SyntaxKind.NamedTupleMember: return node.data.symbol; + case SyntaxKind.BindingElement: return node.data.symbol; + case SyntaxKind.ObjectLiteralExpression: return node.data.symbol; + case SyntaxKind.PropertyAccessExpression: return node.data.symbol; + case SyntaxKind.ElementAccessExpression: return node.data.symbol; + case SyntaxKind.CallExpression: return node.data.symbol; + case SyntaxKind.NewExpression: return node.data.symbol; + case SyntaxKind.FunctionExpression: return node.data.symbol; + case SyntaxKind.ArrowFunction: return node.data.symbol; + case SyntaxKind.BinaryExpression: return node.data.symbol; + case SyntaxKind.ClassExpression: return node.data.symbol; + case SyntaxKind.VariableDeclaration: return node.data.symbol; + case SyntaxKind.FunctionDeclaration: return node.data.symbol; + case SyntaxKind.ClassDeclaration: return node.data.symbol; + case SyntaxKind.InterfaceDeclaration: return node.data.symbol; + case SyntaxKind.TypeAliasDeclaration: return node.data.symbol; + case SyntaxKind.EnumDeclaration: return node.data.symbol; + case SyntaxKind.ModuleDeclaration: return node.data.symbol; + case SyntaxKind.NamespaceExportDeclaration: return node.data.symbol; + case SyntaxKind.ImportEqualsDeclaration: return node.data.symbol; + case SyntaxKind.ImportDeclaration: return node.data.symbol; + case SyntaxKind.ImportClause: return node.data.symbol; + case SyntaxKind.NamespaceImport: return node.data.symbol; + case SyntaxKind.ImportSpecifier: return node.data.symbol; + case SyntaxKind.ExportAssignment: return node.data.symbol; + case SyntaxKind.ExportDeclaration: return node.data.symbol; + case SyntaxKind.NamespaceExport: return node.data.symbol; + case SyntaxKind.ExportSpecifier: return node.data.symbol; + case SyntaxKind.MissingDeclaration: return node.data.symbol; + case SyntaxKind.JsxAttribute: return node.data.symbol; + case SyntaxKind.JsxAttributes: return node.data.symbol; + case SyntaxKind.PropertyAssignment: return node.data.symbol; + case SyntaxKind.ShorthandPropertyAssignment: return node.data.symbol; + case SyntaxKind.SpreadAssignment: return node.data.symbol; + case SyntaxKind.EnumMember: return node.data.symbol; + case SyntaxKind.SourceFile: return node.data.declaration.symbol; + case SyntaxKind.JSDocFunctionType: return node.data.symbol; + case SyntaxKind.JSDocTypeLiteral: return node.data.symbol; + case SyntaxKind.JSDocSignature: return node.data.symbol; + case SyntaxKind.JSDocCallbackTag: return node.data.symbol; + case SyntaxKind.JSDocEnumTag: return node.data.symbol; + case SyntaxKind.JSDocParameterTag: return node.data.symbol; + case SyntaxKind.JSDocTypedefTag: return node.data.symbol; + case SyntaxKind.JSDocPropertyTag: return node.data.symbol; + case SyntaxKind.NotEmittedTypeElement: return node.data.symbol; + default: + Debug.assertNeverTypeOnly(node); // ensures `astGetSymbol` is up-to-date with `AstHasSymbol`/`HasSymbol` + return undefined; + } +} + +/** @internal */ +export function astSetSymbol(node: AstHasSymbol, value: Symbol): Symbol { + // NOTE: each branch is duplicated to remain monomorphic + switch (node.kind) { + case SyntaxKind.NumericLiteral: return node.data.symbol = value; + case SyntaxKind.StringLiteral: return node.data.symbol = value; + case SyntaxKind.NoSubstitutionTemplateLiteral: return node.data.symbol = value; + case SyntaxKind.Identifier: return node.data.symbol = value; + case SyntaxKind.TypeParameter: return node.data.symbol = value; + case SyntaxKind.Parameter: return node.data.symbol = value; + case SyntaxKind.PropertySignature: return node.data.symbol = value; + case SyntaxKind.PropertyDeclaration: return node.data.symbol = value; + case SyntaxKind.MethodSignature: return node.data.symbol = value; + case SyntaxKind.MethodDeclaration: return node.data.symbol = value; + case SyntaxKind.ClassStaticBlockDeclaration: return node.data.symbol = value; + case SyntaxKind.Constructor: return node.data.symbol = value; + case SyntaxKind.GetAccessor: return node.data.symbol = value; + case SyntaxKind.SetAccessor: return node.data.symbol = value; + case SyntaxKind.CallSignature: return node.data.symbol = value; + case SyntaxKind.ConstructSignature: return node.data.symbol = value; + case SyntaxKind.IndexSignature: return node.data.symbol = value; + case SyntaxKind.FunctionType: return node.data.symbol = value; + case SyntaxKind.ConstructorType: return node.data.symbol = value; + case SyntaxKind.TypeLiteral: return node.data.symbol = value; + case SyntaxKind.MappedType: return node.data.symbol = value; + case SyntaxKind.NamedTupleMember: return node.data.symbol = value; + case SyntaxKind.BindingElement: return node.data.symbol = value; + case SyntaxKind.ObjectLiteralExpression: return node.data.symbol = value; + case SyntaxKind.PropertyAccessExpression: return node.data.symbol = value; + case SyntaxKind.ElementAccessExpression: return node.data.symbol = value; + case SyntaxKind.CallExpression: return node.data.symbol = value; + case SyntaxKind.NewExpression: return node.data.symbol = value; + case SyntaxKind.FunctionExpression: return node.data.symbol = value; + case SyntaxKind.ArrowFunction: return node.data.symbol = value; + case SyntaxKind.BinaryExpression: return node.data.symbol = value; + case SyntaxKind.ClassExpression: return node.data.symbol = value; + case SyntaxKind.VariableDeclaration: return node.data.symbol = value; + case SyntaxKind.FunctionDeclaration: return node.data.symbol = value; + case SyntaxKind.ClassDeclaration: return node.data.symbol = value; + case SyntaxKind.InterfaceDeclaration: return node.data.symbol = value; + case SyntaxKind.TypeAliasDeclaration: return node.data.symbol = value; + case SyntaxKind.EnumDeclaration: return node.data.symbol = value; + case SyntaxKind.ModuleDeclaration: return node.data.symbol = value; + case SyntaxKind.NamespaceExportDeclaration: return node.data.symbol = value; + case SyntaxKind.ImportEqualsDeclaration: return node.data.symbol = value; + case SyntaxKind.ImportDeclaration: return node.data.symbol = value; + case SyntaxKind.ImportClause: return node.data.symbol = value; + case SyntaxKind.NamespaceImport: return node.data.symbol = value; + case SyntaxKind.ImportSpecifier: return node.data.symbol = value; + case SyntaxKind.ExportAssignment: return node.data.symbol = value; + case SyntaxKind.ExportDeclaration: return node.data.symbol = value; + case SyntaxKind.NamespaceExport: return node.data.symbol = value; + case SyntaxKind.ExportSpecifier: return node.data.symbol = value; + case SyntaxKind.MissingDeclaration: return node.data.symbol = value; + case SyntaxKind.JsxAttribute: return node.data.symbol = value; + case SyntaxKind.JsxAttributes: return node.data.symbol = value; + case SyntaxKind.PropertyAssignment: return node.data.symbol = value; + case SyntaxKind.ShorthandPropertyAssignment: return node.data.symbol = value; + case SyntaxKind.SpreadAssignment: return node.data.symbol = value; + case SyntaxKind.EnumMember: return node.data.symbol = value; + case SyntaxKind.SourceFile: return node.data.declaration.symbol = value; + case SyntaxKind.JSDocFunctionType: return node.data.symbol = value; + case SyntaxKind.JSDocTypeLiteral: return node.data.symbol = value; + case SyntaxKind.JSDocSignature: return node.data.symbol = value; + case SyntaxKind.JSDocCallbackTag: return node.data.symbol = value; + case SyntaxKind.JSDocEnumTag: return node.data.symbol = value; + case SyntaxKind.JSDocParameterTag: return node.data.symbol = value; + case SyntaxKind.JSDocTypedefTag: return node.data.symbol = value; + case SyntaxKind.JSDocPropertyTag: return node.data.symbol = value; + case SyntaxKind.NotEmittedTypeElement: return node.data.symbol = value; + default: + Debug.assertNever(node); // ensures `astSetSymbol` is up-to-date with `AstHasSymbol`/`HasSymbol` + } +} + +/** @internal */ +export function astGetLocalSymbol(node: AstNode): Symbol | undefined; +export function astGetLocalSymbol(node: AstNode) { + Debug.type(node); // ensures `astGetLocalSymbol` is up-to-date with `AstHasSymbol`/`HasSymbol` + // NOTE: each branch is duplicated to remain monomorphic + switch (node.kind) { + case SyntaxKind.NumericLiteral: return node.data.localSymbol; + case SyntaxKind.StringLiteral: return node.data.localSymbol; + case SyntaxKind.NoSubstitutionTemplateLiteral: return node.data.localSymbol; + case SyntaxKind.Identifier: return node.data.localSymbol; + case SyntaxKind.TypeParameter: return node.data.localSymbol; + case SyntaxKind.Parameter: return node.data.localSymbol; + case SyntaxKind.PropertySignature: return node.data.localSymbol; + case SyntaxKind.PropertyDeclaration: return node.data.localSymbol; + case SyntaxKind.MethodSignature: return node.data.localSymbol; + case SyntaxKind.MethodDeclaration: return node.data.localSymbol; + case SyntaxKind.ClassStaticBlockDeclaration: return node.data.localSymbol; + case SyntaxKind.Constructor: return node.data.localSymbol; + case SyntaxKind.GetAccessor: return node.data.localSymbol; + case SyntaxKind.SetAccessor: return node.data.localSymbol; + case SyntaxKind.CallSignature: return node.data.localSymbol; + case SyntaxKind.ConstructSignature: return node.data.localSymbol; + case SyntaxKind.IndexSignature: return node.data.localSymbol; + case SyntaxKind.FunctionType: return node.data.localSymbol; + case SyntaxKind.ConstructorType: return node.data.localSymbol; + case SyntaxKind.TypeLiteral: return node.data.localSymbol; + case SyntaxKind.MappedType: return node.data.localSymbol; + case SyntaxKind.NamedTupleMember: return node.data.localSymbol; + case SyntaxKind.BindingElement: return node.data.localSymbol; + case SyntaxKind.ObjectLiteralExpression: return node.data.localSymbol; + case SyntaxKind.PropertyAccessExpression: return node.data.localSymbol; + case SyntaxKind.ElementAccessExpression: return node.data.localSymbol; + case SyntaxKind.CallExpression: return node.data.localSymbol; + case SyntaxKind.NewExpression: return node.data.localSymbol; + case SyntaxKind.FunctionExpression: return node.data.localSymbol; + case SyntaxKind.ArrowFunction: return node.data.localSymbol; + case SyntaxKind.BinaryExpression: return node.data.localSymbol; + case SyntaxKind.ClassExpression: return node.data.localSymbol; + case SyntaxKind.VariableDeclaration: return node.data.localSymbol; + case SyntaxKind.FunctionDeclaration: return node.data.localSymbol; + case SyntaxKind.ClassDeclaration: return node.data.localSymbol; + case SyntaxKind.InterfaceDeclaration: return node.data.localSymbol; + case SyntaxKind.TypeAliasDeclaration: return node.data.localSymbol; + case SyntaxKind.EnumDeclaration: return node.data.localSymbol; + case SyntaxKind.ModuleDeclaration: return node.data.localSymbol; + case SyntaxKind.NamespaceExportDeclaration: return node.data.localSymbol; + case SyntaxKind.ImportEqualsDeclaration: return node.data.localSymbol; + case SyntaxKind.ImportDeclaration: return node.data.localSymbol; + case SyntaxKind.ImportClause: return node.data.localSymbol; + case SyntaxKind.NamespaceImport: return node.data.localSymbol; + case SyntaxKind.ImportSpecifier: return node.data.localSymbol; + case SyntaxKind.ExportAssignment: return node.data.localSymbol; + case SyntaxKind.ExportDeclaration: return node.data.localSymbol; + case SyntaxKind.NamespaceExport: return node.data.localSymbol; + case SyntaxKind.ExportSpecifier: return node.data.localSymbol; + case SyntaxKind.MissingDeclaration: return node.data.localSymbol; + case SyntaxKind.JsxAttribute: return node.data.localSymbol; + case SyntaxKind.JsxAttributes: return node.data.localSymbol; + case SyntaxKind.PropertyAssignment: return node.data.localSymbol; + case SyntaxKind.ShorthandPropertyAssignment: return node.data.localSymbol; + case SyntaxKind.SpreadAssignment: return node.data.localSymbol; + case SyntaxKind.EnumMember: return node.data.localSymbol; + case SyntaxKind.SourceFile: return node.data.declaration.localSymbol; + case SyntaxKind.JSDocFunctionType: return node.data.localSymbol; + case SyntaxKind.JSDocTypeLiteral: return node.data.localSymbol; + case SyntaxKind.JSDocSignature: return node.data.localSymbol; + case SyntaxKind.JSDocCallbackTag: return node.data.localSymbol; + case SyntaxKind.JSDocEnumTag: return node.data.localSymbol; + case SyntaxKind.JSDocParameterTag: return node.data.localSymbol; + case SyntaxKind.JSDocTypedefTag: return node.data.localSymbol; + case SyntaxKind.JSDocPropertyTag: return node.data.localSymbol; + case SyntaxKind.NotEmittedTypeElement: return node.data.localSymbol; + default: + Debug.assertNeverTypeOnly(node); // ensures `astGetLocalSymbol` is up-to-date with `AstHasSymbol`/`HasSymbol` + return undefined; + } +} + +/** @internal */ +export function astSetLocalSymbol(node: AstHasSymbol, value: Symbol | undefined): Symbol | undefined { + // NOTE: each branch is duplicated to remain monomorphic + switch (node.kind) { + case SyntaxKind.NumericLiteral: return node.data.localSymbol = value; + case SyntaxKind.StringLiteral: return node.data.localSymbol = value; + case SyntaxKind.NoSubstitutionTemplateLiteral: return node.data.localSymbol = value; + case SyntaxKind.Identifier: return node.data.localSymbol = value; + case SyntaxKind.TypeParameter: return node.data.localSymbol = value; + case SyntaxKind.Parameter: return node.data.localSymbol = value; + case SyntaxKind.PropertySignature: return node.data.localSymbol = value; + case SyntaxKind.PropertyDeclaration: return node.data.localSymbol = value; + case SyntaxKind.MethodSignature: return node.data.localSymbol = value; + case SyntaxKind.MethodDeclaration: return node.data.localSymbol = value; + case SyntaxKind.ClassStaticBlockDeclaration: return node.data.localSymbol = value; + case SyntaxKind.Constructor: return node.data.localSymbol = value; + case SyntaxKind.GetAccessor: return node.data.localSymbol = value; + case SyntaxKind.SetAccessor: return node.data.localSymbol = value; + case SyntaxKind.CallSignature: return node.data.localSymbol = value; + case SyntaxKind.ConstructSignature: return node.data.localSymbol = value; + case SyntaxKind.IndexSignature: return node.data.localSymbol = value; + case SyntaxKind.FunctionType: return node.data.localSymbol = value; + case SyntaxKind.ConstructorType: return node.data.localSymbol = value; + case SyntaxKind.TypeLiteral: return node.data.localSymbol = value; + case SyntaxKind.MappedType: return node.data.localSymbol = value; + case SyntaxKind.NamedTupleMember: return node.data.localSymbol = value; + case SyntaxKind.BindingElement: return node.data.localSymbol = value; + case SyntaxKind.ObjectLiteralExpression: return node.data.localSymbol = value; + case SyntaxKind.PropertyAccessExpression: return node.data.localSymbol = value; + case SyntaxKind.ElementAccessExpression: return node.data.localSymbol = value; + case SyntaxKind.CallExpression: return node.data.localSymbol = value; + case SyntaxKind.NewExpression: return node.data.localSymbol = value; + case SyntaxKind.FunctionExpression: return node.data.localSymbol = value; + case SyntaxKind.ArrowFunction: return node.data.localSymbol = value; + case SyntaxKind.BinaryExpression: return node.data.localSymbol = value; + case SyntaxKind.ClassExpression: return node.data.localSymbol = value; + case SyntaxKind.VariableDeclaration: return node.data.localSymbol = value; + case SyntaxKind.FunctionDeclaration: return node.data.localSymbol = value; + case SyntaxKind.ClassDeclaration: return node.data.localSymbol = value; + case SyntaxKind.InterfaceDeclaration: return node.data.localSymbol = value; + case SyntaxKind.TypeAliasDeclaration: return node.data.localSymbol = value; + case SyntaxKind.EnumDeclaration: return node.data.localSymbol = value; + case SyntaxKind.ModuleDeclaration: return node.data.localSymbol = value; + case SyntaxKind.NamespaceExportDeclaration: return node.data.localSymbol = value; + case SyntaxKind.ImportEqualsDeclaration: return node.data.localSymbol = value; + case SyntaxKind.ImportDeclaration: return node.data.localSymbol = value; + case SyntaxKind.ImportClause: return node.data.localSymbol = value; + case SyntaxKind.NamespaceImport: return node.data.localSymbol = value; + case SyntaxKind.ImportSpecifier: return node.data.localSymbol = value; + case SyntaxKind.ExportAssignment: return node.data.localSymbol = value; + case SyntaxKind.ExportDeclaration: return node.data.localSymbol = value; + case SyntaxKind.NamespaceExport: return node.data.localSymbol = value; + case SyntaxKind.ExportSpecifier: return node.data.localSymbol = value; + case SyntaxKind.MissingDeclaration: return node.data.localSymbol = value; + case SyntaxKind.JsxAttribute: return node.data.localSymbol = value; + case SyntaxKind.JsxAttributes: return node.data.localSymbol = value; + case SyntaxKind.PropertyAssignment: return node.data.localSymbol = value; + case SyntaxKind.ShorthandPropertyAssignment: return node.data.localSymbol = value; + case SyntaxKind.SpreadAssignment: return node.data.localSymbol = value; + case SyntaxKind.EnumMember: return node.data.localSymbol = value; + case SyntaxKind.SourceFile: return node.data.declaration.localSymbol = value; + case SyntaxKind.JSDocFunctionType: return node.data.localSymbol = value; + case SyntaxKind.JSDocTypeLiteral: return node.data.localSymbol = value; + case SyntaxKind.JSDocSignature: return node.data.localSymbol = value; + case SyntaxKind.JSDocCallbackTag: return node.data.localSymbol = value; + case SyntaxKind.JSDocEnumTag: return node.data.localSymbol = value; + case SyntaxKind.JSDocParameterTag: return node.data.localSymbol = value; + case SyntaxKind.JSDocTypedefTag: return node.data.localSymbol = value; + case SyntaxKind.JSDocPropertyTag: return node.data.localSymbol = value; + case SyntaxKind.NotEmittedTypeElement: return node.data.localSymbol = value; + default: + Debug.assertNever(node); // ensures `astSetLocalSymbol` is up-to-date with `AstHasSymbol`/`HasSymbol` + } +} + +/** @internal */ +export function astGetLocals(node: AstNode): SymbolTable | undefined { + Debug.type(node); // ensures `astGetLocals` is up-to-date with `AstHasLocals`/`HasLocals` + // NOTE: each branch is duplicated to remain monomorphic + switch (node.kind) { + case SyntaxKind.MethodSignature: return node.data.locals; + case SyntaxKind.MethodDeclaration: return node.data.locals; + case SyntaxKind.ClassStaticBlockDeclaration: return node.data.locals; + case SyntaxKind.Constructor: return node.data.locals; + case SyntaxKind.GetAccessor: return node.data.locals; + case SyntaxKind.SetAccessor: return node.data.locals; + case SyntaxKind.CallSignature: return node.data.locals; + case SyntaxKind.ConstructSignature: return node.data.locals; + case SyntaxKind.IndexSignature: return node.data.locals; + case SyntaxKind.FunctionType: return node.data.locals; + case SyntaxKind.ConstructorType: return node.data.locals; + case SyntaxKind.ConditionalType: return node.data.locals; + case SyntaxKind.MappedType: return node.data.locals; + case SyntaxKind.FunctionExpression: return node.data.locals; + case SyntaxKind.ArrowFunction: return node.data.locals; + case SyntaxKind.Block: return node.data.locals; + case SyntaxKind.ForStatement: return node.data.locals; + case SyntaxKind.ForInStatement: return node.data.locals; + case SyntaxKind.ForOfStatement: return node.data.locals; + case SyntaxKind.FunctionDeclaration: return node.data.locals; + case SyntaxKind.TypeAliasDeclaration: return node.data.locals; + case SyntaxKind.ModuleDeclaration: return node.data.locals; + case SyntaxKind.CaseBlock: return node.data.locals; + case SyntaxKind.CatchClause: return node.data.locals; + case SyntaxKind.SourceFile: return node.data.locals; + case SyntaxKind.JSDocFunctionType: return node.data.locals; + case SyntaxKind.JSDocSignature: return node.data.locals; + case SyntaxKind.JSDocCallbackTag: return node.data.locals; + case SyntaxKind.JSDocEnumTag: return node.data.locals; + case SyntaxKind.JSDocTypedefTag: return node.data.locals; + default: + Debug.assertNeverTypeOnly(node); // ensures `astGetLocals` is up-to-date with `AstHasLocals`/`HasLocals` + return undefined; + } +} + +/** @internal */ +export function astSetLocals(node: AstHasLocals, value: SymbolTable | undefined): SymbolTable | undefined { + // NOTE: each branch is duplicated to remain monomorphic + switch (node.kind) { + case SyntaxKind.MethodSignature: return node.data.locals = value; + case SyntaxKind.MethodDeclaration: return node.data.locals = value; + case SyntaxKind.ClassStaticBlockDeclaration: return node.data.locals = value; + case SyntaxKind.Constructor: return node.data.locals = value; + case SyntaxKind.GetAccessor: return node.data.locals = value; + case SyntaxKind.SetAccessor: return node.data.locals = value; + case SyntaxKind.CallSignature: return node.data.locals = value; + case SyntaxKind.ConstructSignature: return node.data.locals = value; + case SyntaxKind.IndexSignature: return node.data.locals = value; + case SyntaxKind.FunctionType: return node.data.locals = value; + case SyntaxKind.ConstructorType: return node.data.locals = value; + case SyntaxKind.ConditionalType: return node.data.locals = value; + case SyntaxKind.MappedType: return node.data.locals = value; + case SyntaxKind.FunctionExpression: return node.data.locals = value; + case SyntaxKind.ArrowFunction: return node.data.locals = value; + case SyntaxKind.Block: return node.data.locals = value; + case SyntaxKind.ForStatement: return node.data.locals = value; + case SyntaxKind.ForInStatement: return node.data.locals = value; + case SyntaxKind.ForOfStatement: return node.data.locals = value; + case SyntaxKind.FunctionDeclaration: return node.data.locals = value; + case SyntaxKind.TypeAliasDeclaration: return node.data.locals = value; + case SyntaxKind.ModuleDeclaration: return node.data.locals = value; + case SyntaxKind.CaseBlock: return node.data.locals = value; + case SyntaxKind.CatchClause: return node.data.locals = value; + case SyntaxKind.SourceFile: return node.data.locals = value; + case SyntaxKind.JSDocFunctionType: return node.data.locals = value; + case SyntaxKind.JSDocSignature: return node.data.locals = value; + case SyntaxKind.JSDocCallbackTag: return node.data.locals = value; + case SyntaxKind.JSDocEnumTag: return node.data.locals = value; + case SyntaxKind.JSDocTypedefTag: return node.data.locals = value; + default: + Debug.assertNever(node); // ensures `astSetLocals` is up-to-date with `AstHasLocals`/`HasLocals` + } +} + +/** @internal */ +export function astGetNextContainer(node: AstNode): AstHasLocals | undefined { + Debug.type(node); // ensures `astGetNextContainer` is up-to-date with `AstHasLocals`/`HasLocals` + // NOTE: each branch is duplicated to remain monomorphic + switch (node.kind) { + case SyntaxKind.MethodSignature: return node.data.nextContainer; + case SyntaxKind.MethodDeclaration: return node.data.nextContainer; + case SyntaxKind.ClassStaticBlockDeclaration: return node.data.nextContainer; + case SyntaxKind.Constructor: return node.data.nextContainer; + case SyntaxKind.GetAccessor: return node.data.nextContainer; + case SyntaxKind.SetAccessor: return node.data.nextContainer; + case SyntaxKind.CallSignature: return node.data.nextContainer; + case SyntaxKind.ConstructSignature: return node.data.nextContainer; + case SyntaxKind.IndexSignature: return node.data.nextContainer; + case SyntaxKind.FunctionType: return node.data.nextContainer; + case SyntaxKind.ConstructorType: return node.data.nextContainer; + case SyntaxKind.ConditionalType: return node.data.nextContainer; + case SyntaxKind.MappedType: return node.data.nextContainer; + case SyntaxKind.FunctionExpression: return node.data.nextContainer; + case SyntaxKind.ArrowFunction: return node.data.nextContainer; + case SyntaxKind.Block: return node.data.nextContainer; + case SyntaxKind.ForStatement: return node.data.nextContainer; + case SyntaxKind.ForInStatement: return node.data.nextContainer; + case SyntaxKind.ForOfStatement: return node.data.nextContainer; + case SyntaxKind.FunctionDeclaration: return node.data.nextContainer; + case SyntaxKind.TypeAliasDeclaration: return node.data.nextContainer; + case SyntaxKind.ModuleDeclaration: return node.data.nextContainer; + case SyntaxKind.CaseBlock: return node.data.nextContainer; + case SyntaxKind.CatchClause: return node.data.nextContainer; + case SyntaxKind.SourceFile: return node.data.nextContainer; + case SyntaxKind.JSDocFunctionType: return node.data.nextContainer; + case SyntaxKind.JSDocSignature: return node.data.nextContainer; + case SyntaxKind.JSDocCallbackTag: return node.data.nextContainer; + case SyntaxKind.JSDocEnumTag: return node.data.nextContainer; + case SyntaxKind.JSDocTypedefTag: return node.data.nextContainer; + default: + Debug.assertNeverTypeOnly(node); // ensures `astGetNextContainer` is up-to-date with `AstHasLocals`/`HasLocals` + return undefined; + } +} + +/** @internal */ +export function astSetNextContainer(node: AstHasLocals, value: AstHasLocals | undefined): AstHasLocals | undefined { + // NOTE: each branch is duplicated to remain monomorphic + switch (node.kind) { + case SyntaxKind.MethodSignature: return node.data.nextContainer = value; + case SyntaxKind.MethodDeclaration: return node.data.nextContainer = value; + case SyntaxKind.ClassStaticBlockDeclaration: return node.data.nextContainer = value; + case SyntaxKind.Constructor: return node.data.nextContainer = value; + case SyntaxKind.GetAccessor: return node.data.nextContainer = value; + case SyntaxKind.SetAccessor: return node.data.nextContainer = value; + case SyntaxKind.CallSignature: return node.data.nextContainer = value; + case SyntaxKind.ConstructSignature: return node.data.nextContainer = value; + case SyntaxKind.IndexSignature: return node.data.nextContainer = value; + case SyntaxKind.FunctionType: return node.data.nextContainer = value; + case SyntaxKind.ConstructorType: return node.data.nextContainer = value; + case SyntaxKind.ConditionalType: return node.data.nextContainer = value; + case SyntaxKind.MappedType: return node.data.nextContainer = value; + case SyntaxKind.FunctionExpression: return node.data.nextContainer = value; + case SyntaxKind.ArrowFunction: return node.data.nextContainer = value; + case SyntaxKind.Block: return node.data.nextContainer = value; + case SyntaxKind.ForStatement: return node.data.nextContainer = value; + case SyntaxKind.ForInStatement: return node.data.nextContainer = value; + case SyntaxKind.ForOfStatement: return node.data.nextContainer = value; + case SyntaxKind.FunctionDeclaration: return node.data.nextContainer = value; + case SyntaxKind.TypeAliasDeclaration: return node.data.nextContainer = value; + case SyntaxKind.ModuleDeclaration: return node.data.nextContainer = value; + case SyntaxKind.CaseBlock: return node.data.nextContainer = value; + case SyntaxKind.CatchClause: return node.data.nextContainer = value; + case SyntaxKind.SourceFile: return node.data.nextContainer = value; + case SyntaxKind.JSDocFunctionType: return node.data.nextContainer = value; + case SyntaxKind.JSDocSignature: return node.data.nextContainer = value; + case SyntaxKind.JSDocCallbackTag: return node.data.nextContainer = value; + case SyntaxKind.JSDocEnumTag: return node.data.nextContainer = value; + case SyntaxKind.JSDocTypedefTag: return node.data.nextContainer = value; + default: + Debug.assertNever(node); // ensures `astSetNextContainer` is up-to-date with `AstHasLocals`/`HasLocals` + } +} + +/** @internal */ +export function astGetType(node: T): AstGetResult; +export function astGetType(node: T) { + Debug.type(node); // ensures `astGetType` is up-to-date with `AstHasType`/`HasType` + // NOTE: each branch is duplicated to remain monomorphic + switch (node.kind) { + case SyntaxKind.Parameter: return node.data.type; + case SyntaxKind.PropertySignature: return node.data.type; + case SyntaxKind.PropertyDeclaration: return node.data.type; + case SyntaxKind.MethodSignature: return node.data.type; + case SyntaxKind.MethodDeclaration: return node.data.type; + case SyntaxKind.Constructor: return node.data.type; + case SyntaxKind.GetAccessor: return node.data.type; + case SyntaxKind.SetAccessor: return node.data.type; + case SyntaxKind.CallSignature: return node.data.type; + case SyntaxKind.ConstructSignature: return node.data.type; + case SyntaxKind.IndexSignature: return node.data.type; + case SyntaxKind.TypePredicate: return node.data.type; + case SyntaxKind.FunctionType: return node.data.type; + case SyntaxKind.ConstructorType: return node.data.type; + case SyntaxKind.ParenthesizedType: return node.data.type; + case SyntaxKind.TypeOperator: return node.data.type; + case SyntaxKind.MappedType: return node.data.type; + case SyntaxKind.TypeAssertionExpression: return node.data.type; + case SyntaxKind.FunctionExpression: return node.data.type; + case SyntaxKind.ArrowFunction: return node.data.type; + case SyntaxKind.AsExpression: return node.data.type; + case SyntaxKind.VariableDeclaration: return node.data.type; + case SyntaxKind.FunctionDeclaration: return node.data.type; + case SyntaxKind.TypeAliasDeclaration: return node.data.type; + case SyntaxKind.JSDocTypeExpression: return node.data.type; + case SyntaxKind.JSDocNullableType: return node.data.type; + case SyntaxKind.JSDocNonNullableType: return node.data.type; + case SyntaxKind.JSDocOptionalType: return node.data.type; + case SyntaxKind.JSDocFunctionType: return node.data.type; + case SyntaxKind.JSDocVariadicType: return node.data.type; + case SyntaxKind.OptionalType: return node.data.type; + case SyntaxKind.RestType: return node.data.type; + case SyntaxKind.NamedTupleMember: return node.data.type; + case SyntaxKind.TemplateLiteralTypeSpan: return node.data.type; + case SyntaxKind.SatisfiesExpression: return node.data.type; + case SyntaxKind.JSDocNamepathType: return node.data.type; + case SyntaxKind.JSDocSignature: return node.data.type; + default: + Debug.assertNeverTypeOnly(node); // ensures `astGetType` is up-to-date with `AstHasType`/`HasType` + return undefined; + } +} + +/** @internal */ +export function astGetTypes(node: T): AstGetResult; +export function astGetTypes(node: AstNode) { + Debug.type(node); // ensures `astGetTypes` is up-to-date with `AstHasTypes`/`HasTypes` + // NOTE: each branch is duplicated to remain monomorphic + switch (node.kind) { + case SyntaxKind.UnionType: return node.data.types; + case SyntaxKind.IntersectionType: return node.data.types; + case SyntaxKind.HeritageClause: return node.data.types; + default: + Debug.assertNeverTypeOnly(node); // ensures `astGetTypes` is up-to-date with `AstHasTypes`/`HasTypes` + return undefined; + } +} + +/** @internal */ +export function astGetTypeParameters(node: T): AstGetResult; +export function astGetTypeParameters(node: AstNode) { + Debug.type(node); // ensures `astGetTypeParameters` is up-to-date with `AstHasTypeParameters`/`HasTypeParameters` + // NOTE: each branch is duplicated to remain monomorphic + switch (node.kind) { + case SyntaxKind.MethodSignature: return node.data.typeParameters; + case SyntaxKind.MethodDeclaration: return node.data.typeParameters; + case SyntaxKind.Constructor: return node.data.typeParameters; + case SyntaxKind.GetAccessor: return node.data.typeParameters; + case SyntaxKind.SetAccessor: return node.data.typeParameters; + case SyntaxKind.CallSignature: return node.data.typeParameters; + case SyntaxKind.ConstructSignature: return node.data.typeParameters; + case SyntaxKind.IndexSignature: return node.data.typeParameters; + case SyntaxKind.FunctionType: return node.data.typeParameters; + case SyntaxKind.ConstructorType: return node.data.typeParameters; + case SyntaxKind.FunctionExpression: return node.data.typeParameters; + case SyntaxKind.ArrowFunction: return node.data.typeParameters; + case SyntaxKind.ClassExpression: return node.data.typeParameters; + case SyntaxKind.FunctionDeclaration: return node.data.typeParameters; + case SyntaxKind.ClassDeclaration: return node.data.typeParameters; + case SyntaxKind.InterfaceDeclaration: return node.data.typeParameters; + case SyntaxKind.TypeAliasDeclaration: return node.data.typeParameters; + case SyntaxKind.JSDocFunctionType: return node.data.typeParameters; + case SyntaxKind.JSDocSignature: return node.data.typeParameters; + case SyntaxKind.JSDocTemplateTag: return node.data.typeParameters; + default: + Debug.assertNeverTypeOnly(node); // ensures `astGetTypeParameters` is up-to-date with `AstHasTypeParameters`/`HasTypeParameters` + return undefined; + } +} + +/** @internal */ +export function astGetParameters(node: T): AstGetResult; +export function astGetParameters(node: AstNode) { + Debug.type(node); // ensures `astGetParameters` is up-to-date with `AstHasParameters`/`HasParameters` + // NOTE: each branch is duplicated to remain monomorphic + switch (node.kind) { + case SyntaxKind.MethodSignature: return node.data.parameters; + case SyntaxKind.MethodDeclaration: return node.data.parameters; + case SyntaxKind.Constructor: return node.data.parameters; + case SyntaxKind.GetAccessor: return node.data.parameters; + case SyntaxKind.SetAccessor: return node.data.parameters; + case SyntaxKind.CallSignature: return node.data.parameters; + case SyntaxKind.ConstructSignature: return node.data.parameters; + case SyntaxKind.IndexSignature: return node.data.parameters; + case SyntaxKind.FunctionType: return node.data.parameters; + case SyntaxKind.ConstructorType: return node.data.parameters; + case SyntaxKind.FunctionExpression: return node.data.parameters; + case SyntaxKind.ArrowFunction: return node.data.parameters; + case SyntaxKind.FunctionDeclaration: return node.data.parameters; + case SyntaxKind.JSDocFunctionType: return node.data.parameters; + case SyntaxKind.JSDocSignature: return node.data.parameters; + default: + Debug.assertNeverTypeOnly(node); // ensures `astGetParameters` is up-to-date with `AstHasParameters`/`HasParameters` + return undefined; + } +} + +/** @internal */ +export function astGetBody(node: T): AstGetResult; +export function astGetBody(node: AstNode) { + Debug.type(node); // ensures `astGetBody` is up-to-date with `AstHasBody`/`HasBody` + // NOTE: each branch is duplicated to remain monomorphic + switch (node.kind) { + case SyntaxKind.MethodDeclaration: return node.data.body; + case SyntaxKind.ClassStaticBlockDeclaration: return node.data.body; + case SyntaxKind.Constructor: return node.data.body; + case SyntaxKind.GetAccessor: return node.data.body; + case SyntaxKind.SetAccessor: return node.data.body; + case SyntaxKind.FunctionExpression: return node.data.body; + case SyntaxKind.ArrowFunction: return node.data.body; + case SyntaxKind.FunctionDeclaration: return node.data.body; + case SyntaxKind.ModuleDeclaration: return node.data.body; + default: + Debug.assertNeverTypeOnly(node); // ensures `astGetBody` is up-to-date with `AstHasBody`/`HasBody` + return undefined; + } +} + +/** @internal */ +export function astGetQuestionToken(node: T): AstGetResult; +export function astGetQuestionToken(node: AstNode) { + Debug.type(node); // ensures `astGetQuestionToken` is up-to-date with `AstHasQuestionToken`/`HasQuestionToken` + // NOTE: each branch is duplicated to remain monomorphic + switch (node.kind) { + case SyntaxKind.Parameter: return node.data.questionToken; + case SyntaxKind.PropertySignature: return node.data.questionToken; + case SyntaxKind.PropertyDeclaration: return node.data.questionToken; + case SyntaxKind.MethodSignature: return node.data.questionToken; + case SyntaxKind.MethodDeclaration: return node.data.questionToken; + case SyntaxKind.MappedType: return node.data.questionToken; + case SyntaxKind.NamedTupleMember: return node.data.questionToken; + case SyntaxKind.ConditionalExpression: return node.data.questionToken; + case SyntaxKind.PropertyAssignment: return node.data.questionToken; + case SyntaxKind.ShorthandPropertyAssignment: return node.data.questionToken; + default: + Debug.assertNeverTypeOnly(node); // ensures `astGetQuestionToken` is up-to-date with `AstHasQuestionToken`/`HasQuestionToken` + return undefined; + } +} + +/** @internal */ +export function astGetTypeArguments(node: T): AstGetResult; +export function astGetTypeArguments(node: AstNode) { + Debug.type(node); // ensures `astGetTypeArguments` is up-to-date with `AstInternalHasTypeArguments`/`InternalHasTypeArguments` + // NOTE: each branch is duplicated to remain monomorphic + switch (node.kind) { + case SyntaxKind.MethodSignature: return node.data.typeArguments; + case SyntaxKind.MethodDeclaration: return node.data.typeArguments; + case SyntaxKind.Constructor: return node.data.typeArguments; + case SyntaxKind.GetAccessor: return node.data.typeArguments; + case SyntaxKind.SetAccessor: return node.data.typeArguments; + case SyntaxKind.CallSignature: return node.data.typeArguments; + case SyntaxKind.ConstructSignature: return node.data.typeArguments; + case SyntaxKind.IndexSignature: return node.data.typeArguments; + case SyntaxKind.TypeReference: return node.data.typeArguments; + case SyntaxKind.FunctionType: return node.data.typeArguments; + case SyntaxKind.ConstructorType: return node.data.typeArguments; + case SyntaxKind.TypeQuery: return node.data.typeArguments; + case SyntaxKind.ImportType: return node.data.typeArguments; + case SyntaxKind.CallExpression: return node.data.typeArguments; + case SyntaxKind.NewExpression: return node.data.typeArguments; + case SyntaxKind.TaggedTemplateExpression: return node.data.typeArguments; + case SyntaxKind.FunctionExpression: return node.data.typeArguments; + case SyntaxKind.ArrowFunction: return node.data.typeArguments; + case SyntaxKind.ExpressionWithTypeArguments: return node.data.typeArguments; + case SyntaxKind.FunctionDeclaration: return node.data.typeArguments; + case SyntaxKind.JsxSelfClosingElement: return node.data.typeArguments; + case SyntaxKind.JsxOpeningElement: return node.data.typeArguments; + case SyntaxKind.JSDocFunctionType: return node.data.typeArguments; + default: + Debug.assertNeverTypeOnly(node); // ensures `astGetTypeArguments` is up-to-date with `AstInternalHasTypeArguments`/`InternalHasTypeArguments` + return undefined; + } +} + +/** @internal */ +export function astGetElements(node: T): AstGetResult; +export function astGetElements(node: AstNode) { + Debug.type(node); // ensures `astGetElements` is up-to-date with `AstHasElements`/`HasElements` + // NOTE: each branch is duplicated to remain monomorphic + switch (node.kind) { + case SyntaxKind.TupleType: return node.data.elements; + case SyntaxKind.ObjectBindingPattern: return node.data.elements; + case SyntaxKind.ArrayBindingPattern: return node.data.elements; + case SyntaxKind.ArrayLiteralExpression: return node.data.elements; + case SyntaxKind.NamedImports: return node.data.elements; + case SyntaxKind.NamedExports: return node.data.elements; + case SyntaxKind.CommaListExpression: return node.data.elements; + case SyntaxKind.ImportAttributes: return node.data.elements; + default: + Debug.assertNeverTypeOnly(node); // ensures `astGetElements` is up-to-date with `AstHasElements`/`HasElements` + return undefined; + } +} + +/** @internal */ +export function astGetMembers(node: T): AstGetResult; +export function astGetMembers(node: AstNode) { + Debug.type(node); // ensures `astGetMembers` is up-to-date with `AstHasMembers`/`HasMembers` + // NOTE: each branch is duplicated to remain monomorphic + switch (node.kind) { + case SyntaxKind.TypeLiteral: return node.data.members; + case SyntaxKind.MappedType: return node.data.members; + case SyntaxKind.ClassExpression: return node.data.members; + case SyntaxKind.ClassDeclaration: return node.data.members; + case SyntaxKind.InterfaceDeclaration: return node.data.members; + case SyntaxKind.EnumDeclaration: return node.data.members; + default: + Debug.assertNeverTypeOnly(node); // ensures `astGetMembers` is up-to-date with `AstHasMembers`/`HasMembers` + return undefined; + } +} + +/** @internal */ +export function astGetStatement(node: T): AstGetResult; +export function astGetStatement(node: AstNode) { + Debug.type(node); // ensures `astGetStatement` is up-to-date with `AstHasStatement`/`HasStatement` + // NOTE: each branch is duplicated to remain monomorphic + switch (node.kind) { + case SyntaxKind.DoStatement: return node.data.statement; + case SyntaxKind.WhileStatement: return node.data.statement; + case SyntaxKind.ForStatement: return node.data.statement; + case SyntaxKind.ForInStatement: return node.data.statement; + case SyntaxKind.ForOfStatement: return node.data.statement; + case SyntaxKind.WithStatement: return node.data.statement; + case SyntaxKind.LabeledStatement: return node.data.statement; + default: + Debug.assertNeverTypeOnly(node); // ensures `astGetStatement` is up-to-date with `AstHasStatement`/`HasStatement` + return undefined; + } +} + +/** @internal */ +export function astGetStatements(node: T): AstGetResult; +export function astGetStatements(node: AstNode) { + Debug.type(node); // ensures `astGetStatements` is up-to-date with `AstHasStatements`/`HasStatements` + // NOTE: each branch is duplicated to remain monomorphic + switch (node.kind) { + case SyntaxKind.Block: return node.data.statements; + case SyntaxKind.ModuleBlock: return node.data.statements; + case SyntaxKind.CaseClause: return node.data.statements; + case SyntaxKind.DefaultClause: return node.data.statements; + case SyntaxKind.SourceFile: return node.data.statements; + default: + Debug.assertNeverTypeOnly(node); // ensures `astGetStatements` is up-to-date with `AstHasStatements`/`HasStatements` + return undefined; + } +} + +/** @internal */ +export function astGetExclamationToken(node: T): AstGetResult; +export function astGetExclamationToken(node: AstNode) { + Debug.type(node); // ensures `astGetExclamationToken` is up-to-date with `AstHasExclamationToken`/`HasExclamationToken` + // NOTE: each branch is duplicated to remain monomorphic + switch (node.kind) { + case SyntaxKind.PropertyDeclaration: return node.data.exclamationToken; + case SyntaxKind.MethodDeclaration: return node.data.exclamationToken; + case SyntaxKind.VariableDeclaration: return node.data.exclamationToken; + case SyntaxKind.PropertyAssignment: return node.data.exclamationToken; + case SyntaxKind.ShorthandPropertyAssignment: return node.data.exclamationToken; + default: + Debug.assertNeverTypeOnly(node); // ensures `astGetExclamationToken` is up-to-date with `AstHasExclamationToken`/`HasExclamationToken` + return undefined; + } +} + +/** @internal */ +export function astGetAsteriskToken(node: T): AstGetResult; +export function astGetAsteriskToken(node: AstNode) { + Debug.type(node); // ensures `astGetAsteriskToken` is up-to-date with `AstHasAsteriskToken`/`HasAsteriskToken` + // NOTE: each branch is duplicated to remain monomorphic + switch (node.kind) { + case SyntaxKind.MethodDeclaration: return node.data.asteriskToken; + case SyntaxKind.FunctionExpression: return node.data.asteriskToken; + case SyntaxKind.YieldExpression: return node.data.asteriskToken; + case SyntaxKind.FunctionDeclaration: return node.data.asteriskToken; + default: + Debug.assertNeverTypeOnly(node); // ensures `astGetAsteriskToken` is up-to-date with `AstHasAsteriskToken`/`HasAsteriskToken` + return undefined; + } +} + +/** @internal */ +export function astGetQuestionDotToken(node: T): AstGetResult; +export function astGetQuestionDotToken(node: AstNode) { + Debug.type(node); // ensures `astGetQuestionDotToken` is up-to-date with `AstHasQuestionDotToken`/`HasQuestionDotToken` + // NOTE: each branch is duplicated to remain monomorphic + switch (node.kind) { + case SyntaxKind.PropertyAccessExpression: return node.data.questionDotToken; + case SyntaxKind.ElementAccessExpression: return node.data.questionDotToken; + case SyntaxKind.CallExpression: return node.data.questionDotToken; + case SyntaxKind.TaggedTemplateExpression: return node.data.questionDotToken; + default: + Debug.assertNeverTypeOnly(node); // ensures `astGetQuestionDotToken` is up-to-date with `AstHasQuestionDotToken`/`HasQuestionDotToken` + return undefined; + } +} + +/** @internal */ +export function astGetIsTypeOnly(node: T): AstGetResult; +export function astGetIsTypeOnly(node: AstNode) { + Debug.type(node); // ensures `astGetIsTypeOnly` is up-to-date with `AstHasIsTypeOnly`/`HasIsTypeOnly` + // NOTE: each branch is duplicated to remain monomorphic + switch (node.kind) { + case SyntaxKind.ImportEqualsDeclaration: return node.data.isTypeOnly; + case SyntaxKind.ImportClause: return node.data.isTypeOnly; + case SyntaxKind.ImportSpecifier: return node.data.isTypeOnly; + case SyntaxKind.ExportDeclaration: return node.data.isTypeOnly; + case SyntaxKind.ExportSpecifier: return node.data.isTypeOnly; + default: + Debug.assertNeverTypeOnly(node); // ensures `astGetIsTypeOnly` is up-to-date with `AstHasIsTypeOnly`/`HasIsTypeOnly` + return undefined; + } +} + +/** @internal */ +export function astGetTagName(node: T): AstGetResult; +export function astGetTagName(node: AstNode) { + Debug.type(node); // ensures `astGetTagName` is up-to-date with `AstHasTagName`/`HasTagName` + // NOTE: each branch is duplicated to remain monomorphic + switch (node.kind) { + case SyntaxKind.JsxSelfClosingElement: return node.data.tagName; + case SyntaxKind.JsxOpeningElement: return node.data.tagName; + case SyntaxKind.JsxClosingElement: return node.data.tagName; + case SyntaxKind.JSDocTag: return node.data.tagName; + case SyntaxKind.JSDocAugmentsTag: return node.data.tagName; + case SyntaxKind.JSDocImplementsTag: return node.data.tagName; + case SyntaxKind.JSDocAuthorTag: return node.data.tagName; + case SyntaxKind.JSDocDeprecatedTag: return node.data.tagName; + case SyntaxKind.JSDocClassTag: return node.data.tagName; + case SyntaxKind.JSDocPublicTag: return node.data.tagName; + case SyntaxKind.JSDocPrivateTag: return node.data.tagName; + case SyntaxKind.JSDocProtectedTag: return node.data.tagName; + case SyntaxKind.JSDocReadonlyTag: return node.data.tagName; + case SyntaxKind.JSDocOverrideTag: return node.data.tagName; + case SyntaxKind.JSDocCallbackTag: return node.data.tagName; + case SyntaxKind.JSDocOverloadTag: return node.data.tagName; + case SyntaxKind.JSDocEnumTag: return node.data.tagName; + case SyntaxKind.JSDocParameterTag: return node.data.tagName; + case SyntaxKind.JSDocReturnTag: return node.data.tagName; + case SyntaxKind.JSDocThisTag: return node.data.tagName; + case SyntaxKind.JSDocTypeTag: return node.data.tagName; + case SyntaxKind.JSDocTemplateTag: return node.data.tagName; + case SyntaxKind.JSDocTypedefTag: return node.data.tagName; + case SyntaxKind.JSDocSeeTag: return node.data.tagName; + case SyntaxKind.JSDocPropertyTag: return node.data.tagName; + case SyntaxKind.JSDocThrowsTag: return node.data.tagName; + case SyntaxKind.JSDocSatisfiesTag: return node.data.tagName; + case SyntaxKind.JSDocImportTag: return node.data.tagName; + default: + Debug.assertNeverTypeOnly(node); // ensures `astGetTagName` is up-to-date with `AstHasTagName`/`HasTagName` + return undefined; + } +} + +/** @internal */ +export function astGetComment(node: T): AstGetResult; +export function astGetComment(node: AstNode) { + Debug.type(node); // ensures `astGetComment` is up-to-date with `AstHasComment`/`HasComment` + // NOTE: each branch is duplicated to remain monomorphic + switch (node.kind) { + case SyntaxKind.JSDoc: return node.data.comment ?? node.data.commentArray; + case SyntaxKind.JSDocTag: return node.data.comment ?? node.data.commentArray; + case SyntaxKind.JSDocAugmentsTag: return node.data.comment ?? node.data.commentArray; + case SyntaxKind.JSDocImplementsTag: return node.data.comment ?? node.data.commentArray; + case SyntaxKind.JSDocAuthorTag: return node.data.comment ?? node.data.commentArray; + case SyntaxKind.JSDocDeprecatedTag: return node.data.comment ?? node.data.commentArray; + case SyntaxKind.JSDocClassTag: return node.data.comment ?? node.data.commentArray; + case SyntaxKind.JSDocPublicTag: return node.data.comment ?? node.data.commentArray; + case SyntaxKind.JSDocPrivateTag: return node.data.comment ?? node.data.commentArray; + case SyntaxKind.JSDocProtectedTag: return node.data.comment ?? node.data.commentArray; + case SyntaxKind.JSDocReadonlyTag: return node.data.comment ?? node.data.commentArray; + case SyntaxKind.JSDocOverrideTag: return node.data.comment ?? node.data.commentArray; + case SyntaxKind.JSDocCallbackTag: return node.data.comment ?? node.data.commentArray; + case SyntaxKind.JSDocOverloadTag: return node.data.comment ?? node.data.commentArray; + case SyntaxKind.JSDocEnumTag: return node.data.comment ?? node.data.commentArray; + case SyntaxKind.JSDocParameterTag: return node.data.comment ?? node.data.commentArray; + case SyntaxKind.JSDocReturnTag: return node.data.comment ?? node.data.commentArray; + case SyntaxKind.JSDocThisTag: return node.data.comment ?? node.data.commentArray; + case SyntaxKind.JSDocTypeTag: return node.data.comment ?? node.data.commentArray; + case SyntaxKind.JSDocTemplateTag: return node.data.comment ?? node.data.commentArray; + case SyntaxKind.JSDocTypedefTag: return node.data.comment ?? node.data.commentArray; + case SyntaxKind.JSDocSeeTag: return node.data.comment ?? node.data.commentArray; + case SyntaxKind.JSDocPropertyTag: return node.data.comment ?? node.data.commentArray; + case SyntaxKind.JSDocThrowsTag: return node.data.comment ?? node.data.commentArray; + case SyntaxKind.JSDocSatisfiesTag: return node.data.comment ?? node.data.commentArray; + case SyntaxKind.JSDocImportTag: return node.data.comment ?? node.data.commentArray; + default: + Debug.assertNeverTypeOnly(node); // ensures `astGetComment` is up-to-date with `AstHasComment`/`HasComment` + return undefined; + } +} + +/** @internal */ +export function astSetComment(node: T, value: string | AstNodeArray | undefined): string | AstNodeArray | undefined { + if (typeof value === "string") { + // NOTE: each branch is duplicated to remain monomorphic + switch (node.kind) { + case SyntaxKind.JSDoc: return node.data.comment = value; + case SyntaxKind.JSDocTag: return node.data.comment = value; + case SyntaxKind.JSDocAugmentsTag: return node.data.comment = value; + case SyntaxKind.JSDocImplementsTag: return node.data.comment = value; + case SyntaxKind.JSDocAuthorTag: return node.data.comment = value; + case SyntaxKind.JSDocDeprecatedTag: return node.data.comment = value; + case SyntaxKind.JSDocClassTag: return node.data.comment = value; + case SyntaxKind.JSDocPublicTag: return node.data.comment = value; + case SyntaxKind.JSDocPrivateTag: return node.data.comment = value; + case SyntaxKind.JSDocProtectedTag: return node.data.comment = value; + case SyntaxKind.JSDocReadonlyTag: return node.data.comment = value; + case SyntaxKind.JSDocOverrideTag: return node.data.comment = value; + case SyntaxKind.JSDocCallbackTag: return node.data.comment = value; + case SyntaxKind.JSDocOverloadTag: return node.data.comment = value; + case SyntaxKind.JSDocEnumTag: return node.data.comment = value; + case SyntaxKind.JSDocParameterTag: return node.data.comment = value; + case SyntaxKind.JSDocReturnTag: return node.data.comment = value; + case SyntaxKind.JSDocThisTag: return node.data.comment = value; + case SyntaxKind.JSDocTypeTag: return node.data.comment = value; + case SyntaxKind.JSDocTemplateTag: return node.data.comment = value; + case SyntaxKind.JSDocTypedefTag: return node.data.comment = value; + case SyntaxKind.JSDocSeeTag: return node.data.comment = value; + case SyntaxKind.JSDocPropertyTag: return node.data.comment = value; + case SyntaxKind.JSDocThrowsTag: return node.data.comment = value; + case SyntaxKind.JSDocSatisfiesTag: return node.data.comment = value; + case SyntaxKind.JSDocImportTag: return node.data.comment = value; + default: + Debug.assertNever(node); // ensures `astSetComment` is up-to-date with `AstHasComment`/`HasComment` + } + } + else { + // NOTE: each branch is duplicated to remain monomorphic + switch (node.kind) { + case SyntaxKind.JSDoc: return node.data.commentArray = value; + case SyntaxKind.JSDocTag: return node.data.commentArray = value; + case SyntaxKind.JSDocAugmentsTag: return node.data.commentArray = value; + case SyntaxKind.JSDocImplementsTag: return node.data.commentArray = value; + case SyntaxKind.JSDocAuthorTag: return node.data.commentArray = value; + case SyntaxKind.JSDocDeprecatedTag: return node.data.commentArray = value; + case SyntaxKind.JSDocClassTag: return node.data.commentArray = value; + case SyntaxKind.JSDocPublicTag: return node.data.commentArray = value; + case SyntaxKind.JSDocPrivateTag: return node.data.commentArray = value; + case SyntaxKind.JSDocProtectedTag: return node.data.commentArray = value; + case SyntaxKind.JSDocReadonlyTag: return node.data.commentArray = value; + case SyntaxKind.JSDocOverrideTag: return node.data.commentArray = value; + case SyntaxKind.JSDocCallbackTag: return node.data.commentArray = value; + case SyntaxKind.JSDocOverloadTag: return node.data.commentArray = value; + case SyntaxKind.JSDocEnumTag: return node.data.commentArray = value; + case SyntaxKind.JSDocParameterTag: return node.data.commentArray = value; + case SyntaxKind.JSDocReturnTag: return node.data.commentArray = value; + case SyntaxKind.JSDocThisTag: return node.data.commentArray = value; + case SyntaxKind.JSDocTypeTag: return node.data.commentArray = value; + case SyntaxKind.JSDocTemplateTag: return node.data.commentArray = value; + case SyntaxKind.JSDocTypedefTag: return node.data.commentArray = value; + case SyntaxKind.JSDocSeeTag: return node.data.commentArray = value; + case SyntaxKind.JSDocPropertyTag: return node.data.commentArray = value; + case SyntaxKind.JSDocThrowsTag: return node.data.commentArray = value; + case SyntaxKind.JSDocSatisfiesTag: return node.data.commentArray = value; + case SyntaxKind.JSDocImportTag: return node.data.commentArray = value; + default: + Debug.assertNever(node); // ensures `astSetComment` is up-to-date with `AstHasComment`/`HasComment` + } + } +} + +// NOTE: each branch is duplicated to remain monomorphic const computeTransformFlagsMap: Partial TransformFlags>> = { [SyntaxKind.EndOfFileToken]: node => node.data.computeTransformFlags(node), [SyntaxKind.ThisKeyword]: node => node.data.computeTransformFlags(node), @@ -5583,7 +7918,52 @@ function computeTransformFlags(node: AstNode) { return fn !== undefined ? fn(node) : node.data.computeTransformFlags(node); } -function isAstPropertyName(node: AstNode): node is AstPropertyName { +function copyDataPropertiesCore(data: AstData, clone: AstData) { + Object.assign(clone, data); +} + +function copyDataProperties(node: AstNode, clone: AstData) { + const fn = copyDataPropertiesMap[node.kind]; + return fn !== undefined ? fn(node.data, clone) : copyDataPropertiesCore(node.data, clone); +} + +function createDataInstanceCore(data: AstData) { + return Object.create(Object.getPrototypeOf(data)); +} + +function createDataInstance(node: AstNode) { + const fn = createDataInstanceMap[node.kind]; + return fn !== undefined ? fn(node.data) : + isTokenKind(node.kind) ? new AstTokenData() : + createDataInstanceCore(node.data); +} + +function cloneData(node: AstNode) { + const clone = createDataInstance(node); + copyDataProperties(node, clone); + return clone; +} + +function cloneNode(node: AstNode) { + const fn = cloneNodeMap[node.kind]; + return fn !== undefined ? fn(node) : cloneNodeCore(node); +} + +function shadowDataCore(data: AstData) { + return Object.create(data); +} + +function shadowData(node: AstNode) { + const fn = shadowDataMap[node.kind]; + return fn !== undefined ? fn(node.data) : shadowDataCore(node.data); +} + +function shadowNode(node: AstNode) { + const fn = shadowNodeMap[node.kind]; + return fn !== undefined ? fn(node) : shadowCore(node); +} + +function astIsPropertyName(node: AstNode): node is AstPropertyName { const kind = node.kind; return kind === SyntaxKind.Identifier || kind === SyntaxKind.PrivateIdentifier @@ -5641,8 +8021,8 @@ export function getAstParseTreeNode(node: AstNode | undefined, nodeTest?: (node: } /** @internal */ -export function isAstJSDocTypeAssertion(node: AstNode): node is AstJSDocTypeAssertion { - return isAstParenthesizedExpression(node) +export function astIsJSDocTypeAssertion(node: AstNode): node is AstJSDocTypeAssertion { + return astIsParenthesizedExpression(node) && !!(node.flags & NodeFlags.JavaScriptFile) && !!getJSDocTypeTag(node.node); // TODO: don't invoke node } @@ -5651,34 +8031,7 @@ export function isAstJSDocTypeAssertion(node: AstNode): node is AstJSDocTypeAsse export type AstOuterExpression = AstNodeOneOf; /** @internal */ -export function isAstOuterExpression(node: AstNode, kinds: OuterExpressionKinds = OuterExpressionKinds.All): node is AstOuterExpression { - switch (node.kind) { - case SyntaxKind.ParenthesizedExpression: - if (kinds & OuterExpressionKinds.ExcludeJSDocTypeAssertion && isAstJSDocTypeAssertion(node)) { - return false; - } - return (kinds & OuterExpressionKinds.Parentheses) !== 0; - case SyntaxKind.TypeAssertionExpression: - case SyntaxKind.AsExpression: - case SyntaxKind.SatisfiesExpression: - return (kinds & OuterExpressionKinds.TypeAssertions) !== 0; - case SyntaxKind.ExpressionWithTypeArguments: - return (kinds & OuterExpressionKinds.ExpressionsWithTypeArguments) !== 0; - case SyntaxKind.NonNullExpression: - return (kinds & OuterExpressionKinds.NonNullAssertions) !== 0; - case SyntaxKind.PartiallyEmittedExpression: - return (kinds & OuterExpressionKinds.PartiallyEmittedExpressions) !== 0; - } - return false; -} - -/** @internal */ -export function skipAstOuterExpressions(node: AstNode, kinds: OuterExpressionKinds = OuterExpressionKinds.All): AstNode { - while (isAstOuterExpression(node, kinds)) { - node = node.data.expression; - } - return node; -} +export type AstWrappedExpression = AstNodeOneOf>; // Temporary `Node` implementation representing every possible `Node` shape. // This is only used for testing and will be removed in favor of the node classes in types.ts @@ -5702,7 +8055,7 @@ class AnyNode extends Node { declare _typeNodeBrand: any; declare _statementBrand: any; declare _jsDocTypeBrand: any; - + override getChildCount(sourceFile?: SourceFileLike): number { if (isTokenKind(this.kind)) { return this.getChildren().length; @@ -5752,25 +8105,25 @@ class AnyNode extends Node { set left(value) { this.ast.data.left = value?.ast; } get right() { return this.ast.data.right?.node; } set right(value) { this.ast.data.right = value?.ast; } - get expression() { return this.ast.data.expression?.node; } + get expression() { return astGetExpression(this.ast)?.node; } set expression(value) { this.ast.data.expression = value?.ast; } - get modifiers() { return this.ast.data.modifiers?.nodes; } + get modifiers() { return astGetModifiers(this.ast)?.nodes; } set modifiers(value) { this.ast.data.modifiers = value?.ast; } - get name() { return this.ast.data.name?.node; } + get name() { return astGetName(this.ast)?.node; } set name(value) { this.ast.data.name = value?.ast; } get constraint() { return this.ast.data.constraint?.node; } set constraint(value) { this.ast.data.constraint = value?.ast; } get default() { return this.ast.data.default?.node; } set default(value) { this.ast.data.default = value?.ast; } - get typeParameters() { return this.ast.data.typeParameters?.nodes; } + get typeParameters(): any { return astGetTypeParameters(this.ast)?.nodes; } set typeParameters(value) { this.ast.data.typeParameters = value?.ast; } - get parameters() { return this.ast.data.parameters?.nodes; } + get parameters() { return astGetParameters(this.ast)?.nodes; } set parameters(value) { this.ast.data.parameters = value?.ast; } get type() { if (this.kind === SyntaxKind.SyntheticExpression) { return this.ast.data.type; } - return this.ast.data.type?.node; + return astGetType(this.ast)?.node; } set type(value) { if (this.kind === SyntaxKind.SyntheticExpression) { @@ -5780,17 +8133,17 @@ class AnyNode extends Node { this.ast.data.type = value?.ast; } } - get typeArguments() { return this.ast.data.typeArguments?.nodes; } + get typeArguments() { return astGetTypeArguments(this.ast)?.nodes; } set typeArguments(value) { this.ast.data.typeArguments = value?.ast; } - get exclamationToken() { return this.ast.data.exclamationToken?.node; } + get exclamationToken() { return astGetExclamationToken(this.ast)?.node; } set exclamationToken(value) { this.ast.data.exclamationToken = value?.ast; } - get initializer() { return this.ast.data.initializer?.node; } + get initializer() { return astGetInitializer(this.ast)?.node; } set initializer(value) { this.ast.data.initializer = value?.ast; } get declarations() { return this.ast.data.declarations.nodes; } set declarations(value) { this.ast.data.declarations = value.ast; } get dotDotDotToken() { return this.ast.data.dotDotDotToken?.node; } set dotDotDotToken(value) { this.ast.data.dotDotDotToken = value?.ast; } - get questionToken() { return this.ast.data.questionToken?.node; } + get questionToken() { return astGetQuestionToken(this.ast)?.node; } set questionToken(value) { this.ast.data.questionToken = value?.ast; } get propertyName() { return this.ast.data.propertyName?.node; } set propertyName(value) { this.ast.data.propertyName = value?.ast; } @@ -5798,11 +8151,11 @@ class AnyNode extends Node { set equalsToken(value) { this.ast.data.equalsToken = value?.ast; } get objectAssignmentInitializer() { return this.ast.data.objectAssignmentInitializer?.node; } set objectAssignmentInitializer(value) { this.ast.data.objectAssignmentInitializer = value?.ast; } - get elements() { return this.ast.data.elements.nodes; } + get elements(): any { return astGetElements(this.ast)?.nodes; } set elements(value) { this.ast.data.elements = value.ast; } - get asteriskToken() { return this.ast.data.asteriskToken?.node; } + get asteriskToken() { return astGetAsteriskToken(this.ast)?.node; } set asteriskToken(value) { this.ast.data.asteriskToken = value?.ast; } - get body() { return this.ast.data.body?.node; } + get body() { return astGetBody(this.ast)?.node; } set body(value) { this.ast.data.body = value?.ast; } get assertClause() { return this.ast.data.assertClause?.node; } set assertClause(value) { this.ast.data.assertClause = value?.ast; } @@ -5826,11 +8179,11 @@ class AnyNode extends Node { set parameterName(value) { this.ast.data.parameterName = value.ast; } get exprName() { return this.ast.data.exprName.node; } set exprName(value) { this.ast.data.exprName = value.ast; } - get members() { return this.ast.data.members?.nodes; } + get members() { return astGetMembers(this.ast)?.nodes; } set members(value) { this.ast.data.members = value?.ast; } get elementType() { return this.ast.data.elementType.node; } set elementType(value) { this.ast.data.elementType = value.ast; } - get types() { return this.ast.data.types.nodes; } + get types() { return astGetTypes(this.ast).nodes; } set types(value) { this.ast.data.types = value.ast; } get checkType() { return this.ast.data.checkType.node; } set checkType(value) { this.ast.data.checkType = value.ast; } @@ -5878,7 +8231,7 @@ class AnyNode extends Node { set equalsGreaterThanToken(value) { this.ast.data.equalsGreaterThanToken = value.ast; } get properties() { return this.ast.data.properties?.nodes; } set properties(value) { this.ast.data.properties = value?.ast; } - get questionDotToken() { return this.ast.data.questionDotToken?.node; } + get questionDotToken() { return astGetQuestionDotToken(this.ast)?.node; } set questionDotToken(value) { this.ast.data.questionDotToken = value?.ast; } get argumentExpression() { return this.ast.data.argumentExpression.node; } set argumentExpression(value) { this.ast.data.argumentExpression = value.ast; } @@ -5898,7 +8251,7 @@ class AnyNode extends Node { set closingElement(value) { this.ast.data.closingElement = value.ast; } get namespace() { return this.ast.data.namespace.node; } set namespace(value) { this.ast.data.namespace = value.ast; } - get tagName() { return this.ast.data.tagName.node; } + get tagName() { return astGetTagName(this.ast).node; } set tagName(value) { this.ast.data.tagName = value.ast; } get openingFragment() { return this.ast.data.openingFragment.node; } set openingFragment(value) { this.ast.data.openingFragment = value.ast; } @@ -5906,7 +8259,7 @@ class AnyNode extends Node { set closingFragment(value) { this.ast.data.closingFragment = value.ast; } get thisArg() { return this.ast.data.thisArg.node; } set thisArg(value) { this.ast.data.thisArg = value.ast; } - get statements() { return this.ast.data.statements.nodes; } + get statements() { return astGetStatements(this.ast).nodes; } set statements(value) { this.ast.data.statements = value.ast; } get declarationList() { return this.ast.data.declarationList.node; } set declarationList(value) { this.ast.data.declarationList = value.ast; } @@ -5914,7 +8267,7 @@ class AnyNode extends Node { set thenStatement(value) { this.ast.data.thenStatement = value.ast; } get elseStatement() { return this.ast.data.elseStatement?.node; } set elseStatement(value) { this.ast.data.elseStatement = value?.ast; } - get statement() { return this.ast.data.statement.node; } + get statement() { return astGetStatement(this.ast).node; } set statement(value) { this.ast.data.statement = value.ast; } get incrementor() { return this.ast.data.incrementor?.node; } set incrementor(value) { this.ast.data.incrementor = value?.ast; } @@ -5942,7 +8295,7 @@ class AnyNode extends Node { set heritageClauses(value) { this.ast.data.heritageClauses = value?.ast; } get token() { return this.ast.data.token; } set token(value) { this.ast.data.token = value; } - get isTypeOnly() { return this.ast.data.isTypeOnly; } + get isTypeOnly(): any { return astGetIsTypeOnly(this.ast); } set isTypeOnly(value) { this.ast.data.isTypeOnly = value; } get moduleReference() { return this.ast.data.moduleReference.node; } set moduleReference(value) { this.ast.data.moduleReference = value.ast; } @@ -5963,7 +8316,7 @@ class AnyNode extends Node { get tags() { return this.ast.data.tags?.nodes; } set tags(value) { this.ast.data.tags = value?.ast; } get comment() { - const comment = this.ast.data.comment; + const comment = astGetComment(this.ast); return typeof comment === "string" ? comment : comment?.nodes; } set comment(value) { this.ast.data.comment = typeof value === "string" ? value : value?.ast; } @@ -5983,13 +8336,13 @@ class AnyNode extends Node { set isArrayType(value) { this.ast.data.isArrayType = value; } get escapedText() { return this.ast.data.escapedText; } set escapedText(value) { this.ast.data.escapedText = value; } - get text() { + get text(): any { switch (this.kind) { case SyntaxKind.Identifier: case SyntaxKind.PrivateIdentifier: - return idText(this as unknown as Identifier | PrivateIdentifier); + return astIdText(this.ast as unknown as AstIdentifier | AstPrivateIdentifier); default: - return this.data.text; + return astGetText(this.ast); } } set text(value) { this.ast.data.text = value; } @@ -6011,20 +8364,20 @@ class AnyNode extends Node { set containsOnlyTriviaWhiteSpaces(value) { this.ast.data.containsOnlyTriviaWhiteSpaces = value; } get resolvedSymbol() { return this.ast.data.resolvedSymbol; } set resolvedSymbol(value) { this.ast.data.resolvedSymbol = value; } - get symbol() { return this.ast.data.symbol; } - set symbol(value) { this.ast.data.symbol = value; } - get localSymbol() { return this.ast.data.localSymbol; } - set localSymbol(value) { this.ast.data.localSymbol = value; } - get jsDoc() { return this.ast.data.jsDoc; } - set jsDoc(value) { this.ast.data.jsDoc = value; } - get flowNode() { return this.ast.data.flowNode; } - set flowNode(value) { this.ast.data.flowNode = value; } - get locals() { return this.ast.data.locals; } - set locals(value) { this.ast.data.locals = value; } - get nextContainer() { return this.ast.data.nextContainer?.node; } - set nextContainer(value) { this.ast.data.nextContainer = value?.ast; } - get endFlowNode() { return this.ast.data.endFlowNode; } - set endFlowNode(value) { this.ast.data.endFlowNode = value; } + get symbol(): any { return astGetSymbol(this.ast); } + set symbol(value) { astSetSymbol(this.ast as AstHasSymbol, value); } + get localSymbol(): any { return astGetLocalSymbol(this.ast); } + set localSymbol(value) { astSetLocalSymbol(this.ast as AstHasSymbol, value); } + get jsDoc() { return astGetJSDoc(this.ast); } + set jsDoc(value) { astSetJSDoc(this.ast as AstHasJSDoc, value); } + get flowNode() { return astGetFlowNode(this.ast); } + set flowNode(value) { astSetFlowNode(this.ast as AstHasFlowNode, value); } + get locals(): any { return astGetLocals(this.ast); } + set locals(value) { astSetLocals(this.ast as AstHasLocals, value); } + get nextContainer(): any { return astGetNextContainer(this.ast)?.node; } + set nextContainer(value) { astSetNextContainer(this.ast as AstHasLocals, value?.ast); } + get endFlowNode() { return astGetEndFlowNode(this.ast); } + set endFlowNode(value) { astSetEndFlowNode(this.ast as AstHasEndFlowNode, value); } get returnFlowNode() { return this.ast.data.returnFlowNode; } set returnFlowNode(value) { this.ast.data.returnFlowNode = value; } get fallthroughFlowNode() { return this.ast.data.fallthroughFlowNode; } diff --git a/src/compiler/astForEachChild.ts b/src/compiler/astForEachChild.ts index f182752c23f..5f3087480d6 100644 --- a/src/compiler/astForEachChild.ts +++ b/src/compiler/astForEachChild.ts @@ -757,13 +757,13 @@ const astForEachChildTable: AstForEachChildTable = { visitNode(cbNode, node.data.type); }, [SyntaxKind.JSDoc]: function forEachChildInJSDoc(node: AstJSDoc, cbNode: (node: AstNode) => T | undefined, cbNodes?: (nodes: AstNodeArray) => T | undefined): T | undefined { - return (typeof node.data.comment === "string" ? undefined : visitNodes(cbNode, cbNodes, node.data.comment)) + return visitNodes(cbNode, cbNodes, node.data.commentArray) || visitNodes(cbNode, cbNodes, node.data.tags); }, [SyntaxKind.JSDocSeeTag]: function forEachChildInJSDocSeeTag(node: AstJSDocSeeTag, cbNode: (node: AstNode) => T | undefined, cbNodes?: (nodes: AstNodeArray) => T | undefined): T | undefined { return visitNode(cbNode, node.data.tagName) || visitNode(cbNode, node.data.name) || - (typeof node.data.comment === "string" ? undefined : visitNodes(cbNode, cbNodes, node.data.comment)); + visitNodes(cbNode, cbNodes, node.data.commentArray); }, [SyntaxKind.JSDocNameReference]: function forEachChildInJSDocNameReference(node: AstJSDocNameReference, cbNode: (node: AstNode) => T | undefined, _cbNodes?: (nodes: AstNodeArray) => T | undefined): T | undefined { return visitNode(cbNode, node.data.name); @@ -776,23 +776,23 @@ const astForEachChildTable: AstForEachChildTable = { [SyntaxKind.JSDocPropertyTag]: forEachChildInJSDocParameterOrPropertyTag, [SyntaxKind.JSDocAuthorTag]: function forEachChildInJSDocAuthorTag(node: AstJSDocAuthorTag, cbNode: (node: AstNode) => T | undefined, cbNodes?: (nodes: AstNodeArray) => T | undefined): T | undefined { return visitNode(cbNode, node.data.tagName) || - (typeof node.data.comment === "string" ? undefined : visitNodes(cbNode, cbNodes, node.data.comment)); + visitNodes(cbNode, cbNodes, node.data.commentArray); }, [SyntaxKind.JSDocImplementsTag]: function forEachChildInJSDocImplementsTag(node: AstJSDocImplementsTag, cbNode: (node: AstNode) => T | undefined, cbNodes?: (nodes: AstNodeArray) => T | undefined): T | undefined { return visitNode(cbNode, node.data.tagName) || visitNode(cbNode, node.data.class) || - (typeof node.data.comment === "string" ? undefined : visitNodes(cbNode, cbNodes, node.data.comment)); + visitNodes(cbNode, cbNodes, node.data.commentArray); }, [SyntaxKind.JSDocAugmentsTag]: function forEachChildInJSDocAugmentsTag(node: AstJSDocAugmentsTag, cbNode: (node: AstNode) => T | undefined, cbNodes?: (nodes: AstNodeArray) => T | undefined): T | undefined { return visitNode(cbNode, node.data.tagName) || visitNode(cbNode, node.data.class) || - (typeof node.data.comment === "string" ? undefined : visitNodes(cbNode, cbNodes, node.data.comment)); + visitNodes(cbNode, cbNodes, node.data.commentArray); }, [SyntaxKind.JSDocTemplateTag]: function forEachChildInJSDocTemplateTag(node: AstJSDocTemplateTag, cbNode: (node: AstNode) => T | undefined, cbNodes?: (nodes: AstNodeArray) => T | undefined): T | undefined { return visitNode(cbNode, node.data.tagName) || visitNode(cbNode, node.data.constraint) || visitNodes(cbNode, cbNodes, node.data.typeParameters) || - (typeof node.data.comment === "string" ? undefined : visitNodes(cbNode, cbNodes, node.data.comment)); + visitNodes(cbNode, cbNodes, node.data.commentArray); }, [SyntaxKind.JSDocTypedefTag]: function forEachChildInJSDocTypedefTag(node: AstJSDocTypedefTag, cbNode: (node: AstNode) => T | undefined, cbNodes?: (nodes: AstNodeArray) => T | undefined): T | undefined { return visitNode(cbNode, node.data.tagName) || @@ -800,16 +800,16 @@ const astForEachChildTable: AstForEachChildTable = { node.data.typeExpression.kind === SyntaxKind.JSDocTypeExpression ? visitNode(cbNode, node.data.typeExpression) || visitNode(cbNode, node.data.fullName) || - (typeof node.data.comment === "string" ? undefined : visitNodes(cbNode, cbNodes, node.data.comment)) + visitNodes(cbNode, cbNodes, node.data.commentArray) : visitNode(cbNode, node.data.fullName) || visitNode(cbNode, node.data.typeExpression) || - (typeof node.data.comment === "string" ? undefined : visitNodes(cbNode, cbNodes, node.data.comment))); + visitNodes(cbNode, cbNodes, node.data.commentArray)); }, [SyntaxKind.JSDocCallbackTag]: function forEachChildInJSDocCallbackTag(node: AstJSDocCallbackTag, cbNode: (node: AstNode) => T | undefined, cbNodes?: (nodes: AstNodeArray) => T | undefined): T | undefined { return visitNode(cbNode, node.data.tagName) || visitNode(cbNode, node.data.fullName) || visitNode(cbNode, node.data.typeExpression) || - (typeof node.data.comment === "string" ? undefined : visitNodes(cbNode, cbNodes, node.data.comment)); + visitNodes(cbNode, cbNodes, node.data.commentArray); }, [SyntaxKind.JSDocReturnTag]: forEachChildInJSDocTypeLikeTag, [SyntaxKind.JSDocTypeTag]: forEachChildInJSDocTypeLikeTag, @@ -901,13 +901,13 @@ function forEachChildInJSDocParameterOrPropertyTag(node: AstJSDocParameterTag (node.data.isNameFirst ? visitNode(cbNode, node.data.name) || visitNode(cbNode, node.data.typeExpression) : visitNode(cbNode, node.data.typeExpression) || visitNode(cbNode, node.data.name)) || - (typeof node.data.comment === "string" ? undefined : visitNodes(cbNode, cbNodes, node.data.comment)); + visitNodes(cbNode, cbNodes, node.data.commentArray); } function forEachChildInJSDocTypeLikeTag(node: AstJSDocReturnTag | AstJSDocTypeTag | AstJSDocThisTag | AstJSDocEnumTag | AstJSDocThrowsTag | AstJSDocOverloadTag | AstJSDocSatisfiesTag, cbNode: (node: AstNode) => T | undefined, cbNodes?: (nodes: AstNodeArray) => T | undefined): T | undefined { return visitNode(cbNode, node.data.tagName) || visitNode(cbNode, node.data.typeExpression) || - (typeof node.data.comment === "string" ? undefined : visitNodes(cbNode, cbNodes, node.data.comment)); + visitNodes(cbNode, cbNodes, node.data.commentArray); } function forEachChildInJSDocLinkCodeOrPlain(node: AstJSDocLink | AstJSDocLinkCode | AstJSDocLinkPlain, cbNode: (node: AstNode) => T | undefined, _cbNodes?: (nodes: AstNodeArray) => T | undefined): T | undefined { @@ -916,7 +916,7 @@ function forEachChildInJSDocLinkCodeOrPlain(node: AstJSDocLink | AstJSDocLink function forEachChildInJSDocTag(node: AstJSDocUnknownTag | AstJSDocClassTag | AstJSDocPublicTag | AstJSDocPrivateTag | AstJSDocProtectedTag | AstJSDocReadonlyTag | AstJSDocDeprecatedTag | AstJSDocOverrideTag, cbNode: (node: AstNode) => T | undefined, cbNodes?: (nodes: AstNodeArray) => T | undefined): T | undefined { return visitNode(cbNode, node.data.tagName) - || (typeof node.data.comment === "string" ? undefined : visitNodes(cbNode, cbNodes, node.data.comment)); + || visitNodes(cbNode, cbNodes, node.data.commentArray); } function forEachChildInJSDocImportTag(node: AstJSDocImportTag, cbNode: (node: AstNode) => T | undefined, cbNodes?: (nodes: AstNodeArray) => T | undefined): T | undefined { @@ -924,7 +924,7 @@ function forEachChildInJSDocImportTag(node: AstJSDocImportTag, cbNode: (node: || visitNode(cbNode, node.data.importClause) || visitNode(cbNode, node.data.moduleSpecifier) || visitNode(cbNode, node.data.attributes) - || (typeof node.data.comment === "string" ? undefined : visitNodes(cbNode, cbNodes, node.data.comment)); + || visitNodes(cbNode, cbNodes, node.data.commentArray); } function forEachChildInPartiallyEmittedExpression(node: AstPartiallyEmittedExpression, cbNode: (node: AstNode) => T | undefined, _cbNodes?: (nodes: AstNodeArray) => T | undefined): T | undefined { diff --git a/src/compiler/binder.ts b/src/compiler/binder.ts index 347970f24f5..130cc7b22ff 100644 --- a/src/compiler/binder.ts +++ b/src/compiler/binder.ts @@ -8,6 +8,94 @@ import { ArrayLiteralExpression, ArrowFunction, AssignmentDeclarationKind, + AstAccessExpression, + AstArrowFunction, + AstBinaryExpression, + AstBindableObjectDefinePropertyCall, + AstBindablePropertyAssignmentExpression, + AstBindableStaticPropertyAssignmentExpression, + AstBindingElement, + AstBlock, + AstCallExpression, + AstCatchClause, + AstClassLikeDeclaration, + AstDeclaration, + AstDeleteExpression, + AstElementAccessExpression, + AstEnumDeclaration, + AstExportAssignment, + AstExportDeclaration, + AstExpression, + AstFunctionDeclaration, + AstFunctionExpression, + astGetAssignmentDeclarationKind, + astGetExpression, + astGetNameOfDeclaration, + astHasDynamicName, + astHasName, + astHasSyntacticModifier, + AstIdentifier, + astIdentifierToKeywordKind, + AstImportClause, + astIsBindableStaticAccessExpression, + astIsEntityNameExpression, + astIsExportSpecifier, + astIsExpression, + astIsIdentifier, + astIsIdentifierName, + astIsInJSFile, + astIsInTopLevelContext, + astIsJSDocTypeAlias, + astIsLeftHandSideExpression, + astIsModuleExportsAccessExpression, + astIsPartOfTypeQuery, + astIsPrototypeAccess, + astIsSpecialPropertyDeclaration, + astIsStringOrNumericLiteralLike, + astIsTypeAliasDeclaration, + AstJSDocCallbackTag, + AstJSDocClassTag, + AstJSDocEnumTag, + AstJSDocImportTag, + AstJSDocOverloadTag, + AstJSDocParameterTag, + AstJSDocPropertyLikeTag, + AstJSDocSignature, + AstJSDocTypedefTag, + AstJSDocTypeLiteral, + AstJsxAttribute, + AstJsxAttributes, + AstLabeledStatement, + AstLiteralLikeElementAccessExpression, + AstMappedTypeNode, + AstMetaProperty, + AstMethodDeclaration, + AstModuleBlock, + AstModuleDeclaration, + astModuleExportNameIsDefault, + AstNamespaceExportDeclaration, + AstNode, + astNodeIsMissing, + AstNonNullExpression, + AstObjectLiteralExpression, + AstParameterDeclaration, + AstParenthesizedExpression, + AstPostfixUnaryExpression, + AstPrefixUnaryExpression, + AstPrivateIdentifier, + AstPropertyAccessExpression, + AstPropertyDeclaration, + AstPropertySignature, + AstQualifiedName, + astSetFlowNode, + AstSignatureDeclaration, + AstSourceFile, + AstSuperExpression, + AstThisExpression, + AstTypeLiteralNode, + AstTypeParameterDeclaration, + AstVariableDeclaration, + AstWithStatement, BinaryExpression, BinaryOperatorToken, BindableAccessExpression, @@ -123,7 +211,6 @@ import { hasName, hasSyntacticModifier, Identifier, - identifierToKeywordKind, idText, IfStatement, ImportClause, @@ -153,13 +240,10 @@ import { isDestructuringAssignment, isDottedName, isEmptyObjectLiteral, - isEntityNameExpression, isEnumConst, isExportAssignment, isExportDeclaration, isExportsIdentifier, - isExportSpecifier, - isExpression, isExpressionOfOptionalChainRoot, isExternalModule, isExternalOrCommonJsModule, @@ -171,9 +255,7 @@ import { isFunctionSymbol, isGlobalScopeAugmentation, isIdentifier, - isIdentifierName, isInJSFile, - isInTopLevelContext, isJSDocConstructSignature, isJSDocEnumTag, isJSDocTemplateTag, @@ -203,7 +285,6 @@ import { isParameterPropertyDeclaration, isParenthesizedExpression, isPartOfParameterDeclaration, - isPartOfTypeQuery, isPrefixUnaryExpression, isPrivateIdentifier, isPrologueDirective, @@ -216,7 +297,6 @@ import { isShorthandPropertyAssignment, isSignedNumericLiteral, isSourceFile, - isSpecialPropertyDeclaration, isStatement, isStatementButNotDeclaration, isStatic, @@ -224,7 +304,6 @@ import { isStringLiteralLike, isStringOrNumericLiteralLike, isThisInitializedDeclaration, - isTypeAliasDeclaration, isTypeOfExpression, isVariableDeclaration, isVariableDeclarationInitializedToBareOrAccessedRequire, @@ -234,9 +313,7 @@ import { JSDocEnumTag, JSDocFunctionType, JSDocImportTag, - JSDocOverloadTag, JSDocParameterTag, - JSDocPropertyLikeTag, JSDocSignature, JSDocTypedefTag, JSDocTypeLiteral, @@ -246,19 +323,15 @@ import { length, LiteralLikeElementAccessExpression, MappedTypeNode, - MetaProperty, MethodDeclaration, ModifierFlags, - ModuleBlock, ModuleDeclaration, - moduleExportNameIsDefault, Mutable, NamespaceExportDeclaration, Node, NodeArray, NodeFlags, nodeHasName, - nodeIsMissing, nodeIsPresent, NonNullChain, NonNullExpression, @@ -271,13 +344,11 @@ import { PatternAmbientModule, PostfixUnaryExpression, PrefixUnaryExpression, - PrivateIdentifier, PropertyAccessChain, PropertyAccessEntityNameExpression, PropertyAccessExpression, PropertyDeclaration, PropertySignature, - QualifiedName, removeFileExtension, ReturnStatement, ScriptTarget, @@ -295,7 +366,6 @@ import { SpreadElement, Statement, StringLiteral, - SuperExpression, SwitchStatement, Symbol, SymbolFlags, @@ -303,7 +373,6 @@ import { SymbolTable, SyntaxKind, TextRange, - ThisExpression, ThrowStatement, tokenToString, tracing, @@ -647,7 +716,7 @@ function createBinder(): (file: SourceFile, options: CompilerOptions) => void { symbol.flags |= symbolFlags; node.symbol = symbol; - symbol.declarations = appendIfUnique(symbol.declarations, node); + symbol.astDeclarations = appendIfUnique(symbol.astDeclarations, node.ast); if (symbolFlags & (SymbolFlags.Class | SymbolFlags.Enum | SymbolFlags.Module | SymbolFlags.Variable) && !symbol.exports) { symbol.exports = createSymbolTable(); @@ -757,15 +826,15 @@ function createBinder(): (file: SourceFile, options: CompilerOptions) => void { * @param includes - The SymbolFlags that node has in addition to its declaration type (eg: export, ambient, etc.) * @param excludes - The flags which node cannot be declared alongside in a symbol table. Used to report forbidden declarations. */ - function declareSymbol(symbolTable: SymbolTable, parent: Symbol | undefined, node: Declaration, includes: SymbolFlags, excludes: SymbolFlags, isReplaceableByMethod?: boolean, isComputedName?: boolean): Symbol { - Debug.assert(isComputedName || !hasDynamicName(node)); + function declareSymbol(symbolTable: SymbolTable, parent: Symbol | undefined, node: AstDeclaration, includes: SymbolFlags, excludes: SymbolFlags, isReplaceableByMethod?: boolean, isComputedName?: boolean): Symbol { + Debug.assert(isComputedName || !astHasDynamicName(node)); - const isDefaultExport = hasSyntacticModifier(node, ModifierFlags.Default) || isExportSpecifier(node) && moduleExportNameIsDefault(node.name); + const isDefaultExport = astHasSyntacticModifier(node, ModifierFlags.Default) || astIsExportSpecifier(node) && astModuleExportNameIsDefault(node.data.name); // The exported symbol for an export default function/class node is always named "default" const name = isComputedName ? InternalSymbolName.Computed : isDefaultExport && parent ? InternalSymbolName.Default - : getDeclarationName(node); + : getDeclarationName(node.node); // TODO(rbuckton): do not instantiate `.node` let symbol: Symbol | undefined; if (name === undefined) { @@ -817,8 +886,8 @@ function createBinder(): (file: SourceFile, options: CompilerOptions) => void { } else if (!(includes & SymbolFlags.Variable && symbol.flags & SymbolFlags.Assignment)) { // Assignment declarations are allowed to merge with variables, no matter what other flags they have. - if (isNamedDeclaration(node)) { - setParent(node.name, node); + if (astHasName(node)) { + node.data.name.parent = node; } // Report errors every position with duplicate declaration // Report errors on previous encountered declarations @@ -849,7 +918,7 @@ function createBinder(): (file: SourceFile, options: CompilerOptions) => void { // 2. multiple export default of export assignment. This one doesn't have NodeFlags.Default on (as export default doesn't considered as modifiers) if ( symbol.declarations && symbol.declarations.length && - (node.kind === SyntaxKind.ExportAssignment && !(node as ExportAssignment).isExportEquals) + (node.kind === SyntaxKind.ExportAssignment && !(node as AstExportAssignment).data.isExportEquals) ) { message = Diagnostics.A_module_cannot_have_multiple_default_exports; messageNeedsName = false; @@ -859,24 +928,24 @@ function createBinder(): (file: SourceFile, options: CompilerOptions) => void { } const relatedInformation: DiagnosticRelatedInformation[] = []; - if (isTypeAliasDeclaration(node) && nodeIsMissing(node.type) && hasSyntacticModifier(node, ModifierFlags.Export) && symbol.flags & (SymbolFlags.Alias | SymbolFlags.Type | SymbolFlags.Namespace)) { + if (astIsTypeAliasDeclaration(node) && astNodeIsMissing(node.data.type) && astHasSyntacticModifier(node, ModifierFlags.Export) && symbol.flags & (SymbolFlags.Alias | SymbolFlags.Type | SymbolFlags.Namespace)) { // export type T; - may have meant export type { T }? - relatedInformation.push(createDiagnosticForNode(node, Diagnostics.Did_you_mean_0, `export type { ${unescapeLeadingUnderscores(node.name.escapedText)} }`)); + relatedInformation.push(createDiagnosticForNode(node.node, Diagnostics.Did_you_mean_0, `export type { ${unescapeLeadingUnderscores(node.data.name.data.escapedText)} }`)); // TODO(rbuckton): do not instantiate `.node` } - const declarationName = getNameOfDeclaration(node) || node; - forEach(symbol.declarations, (declaration, index) => { + const declarationName = astGetNameOfDeclaration(node) ?? node; + forEach(symbol.declarations, (declaration, index) => { // TODO(rbuckton): AstNode version of `declarations` const decl = getNameOfDeclaration(declaration) || declaration; const diag = messageNeedsName ? createDiagnosticForNode(decl, message, getDisplayName(declaration)) : createDiagnosticForNode(decl, message); file.bindDiagnostics.push( - multipleDefaultExports ? addRelatedInfo(diag, createDiagnosticForNode(declarationName, index === 0 ? Diagnostics.Another_export_default_is_here : Diagnostics.and_here)) : diag, + multipleDefaultExports ? addRelatedInfo(diag, createDiagnosticForNode(declarationName.node, index === 0 ? Diagnostics.Another_export_default_is_here : Diagnostics.and_here)) : diag, // TODO(rbuckton): do not instantiate `.node` ); if (multipleDefaultExports) { relatedInformation.push(createDiagnosticForNode(decl, Diagnostics.The_first_export_default_is_here)); } }); - const diag = messageNeedsName ? createDiagnosticForNode(declarationName, message, getDisplayName(node)) : createDiagnosticForNode(declarationName, message); + const diag = messageNeedsName ? createDiagnosticForNode(declarationName.node, message, getDisplayName(node.node)) : createDiagnosticForNode(declarationName.node, message); // TODO(rbuckton): do not instantiate `.node` file.bindDiagnostics.push(addRelatedInfo(diag, ...relatedInformation)); symbol = createSymbol(SymbolFlags.None, name); @@ -884,7 +953,7 @@ function createBinder(): (file: SourceFile, options: CompilerOptions) => void { } } - addDeclarationToSymbol(symbol, node, includes); + addDeclarationToSymbol(symbol, node.node, includes); // TODO(rbuckton): do not instantiate `.node` if (symbol.parent) { Debug.assert(symbol.parent === parent, "Existing symbol parent should match new one"); } @@ -899,11 +968,11 @@ function createBinder(): (file: SourceFile, options: CompilerOptions) => void { const hasExportModifier = !!(getCombinedModifierFlags(node) & ModifierFlags.Export) || jsdocTreatAsExported(node); if (symbolFlags & SymbolFlags.Alias) { if (node.kind === SyntaxKind.ExportSpecifier || (node.kind === SyntaxKind.ImportEqualsDeclaration && hasExportModifier)) { - return declareSymbol(container.symbol.exports!, container.symbol, node, symbolFlags, symbolExcludes); + return declareSymbol(container.symbol.exports!, container.symbol, node.ast, symbolFlags, symbolExcludes); } else { Debug.assertNode(container, canHaveLocals); - return declareSymbol(container.locals!, /*parent*/ undefined, node, symbolFlags, symbolExcludes); + return declareSymbol(container.locals!, /*parent*/ undefined, node.ast, symbolFlags, symbolExcludes); } } else { @@ -925,17 +994,17 @@ function createBinder(): (file: SourceFile, options: CompilerOptions) => void { 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 (!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! + return declareSymbol(container.symbol.exports!, container.symbol, node.ast, symbolFlags, symbolExcludes); // No local symbol for an unnamed default! } const exportKind = symbolFlags & SymbolFlags.Value ? SymbolFlags.ExportValue : 0; - const local = declareSymbol(container.locals, /*parent*/ undefined, node, exportKind, symbolExcludes); - local.exportSymbol = declareSymbol(container.symbol.exports!, container.symbol, node, symbolFlags, symbolExcludes); + const local = declareSymbol(container.locals, /*parent*/ undefined, node.ast, exportKind, symbolExcludes); + local.exportSymbol = declareSymbol(container.symbol.exports!, container.symbol, node.ast, symbolFlags, symbolExcludes); node.localSymbol = local; return local; } else { Debug.assertNode(container, canHaveLocals); - return declareSymbol(container.locals!, /*parent*/ undefined, node, symbolFlags, symbolExcludes); + return declareSymbol(container.locals!, /*parent*/ undefined, node.ast, symbolFlags, symbolExcludes); } } } @@ -1254,7 +1323,7 @@ function createBinder(): (file: SourceFile, options: CompilerOptions) => void { return false; } - function isNarrowableReference(expr: Expression): boolean { + function isNarrowableReference(expr: AstExpression): boolean { switch (expr.kind) { case SyntaxKind.Identifier: case SyntaxKind.ThisKeyword: @@ -1264,19 +1333,19 @@ function createBinder(): (file: SourceFile, options: CompilerOptions) => void { case SyntaxKind.PropertyAccessExpression: case SyntaxKind.ParenthesizedExpression: case SyntaxKind.NonNullExpression: - return isNarrowableReference((expr as PropertyAccessExpression | ParenthesizedExpression | NonNullExpression).expression); + return isNarrowableReference(astGetExpression(expr as AstPropertyAccessExpression | AstParenthesizedExpression | AstNonNullExpression)); case SyntaxKind.ElementAccessExpression: - return (isStringOrNumericLiteralLike((expr as ElementAccessExpression).argumentExpression) || isEntityNameExpression((expr as ElementAccessExpression).argumentExpression)) && - isNarrowableReference((expr as ElementAccessExpression).expression); + return (astIsStringOrNumericLiteralLike((expr as AstElementAccessExpression).data.argumentExpression) || astIsEntityNameExpression((expr as AstElementAccessExpression).data.argumentExpression)) && + isNarrowableReference((expr as AstElementAccessExpression).data.expression); case SyntaxKind.BinaryExpression: - return (expr as BinaryExpression).operatorToken.kind === SyntaxKind.CommaToken && isNarrowableReference((expr as BinaryExpression).right) || - isAssignmentOperator((expr as BinaryExpression).operatorToken.kind) && isLeftHandSideExpression((expr as BinaryExpression).left); + return (expr as AstBinaryExpression).data.operatorToken.kind === SyntaxKind.CommaToken && isNarrowableReference((expr as AstBinaryExpression).data.right) || + isAssignmentOperator((expr as AstBinaryExpression).data.operatorToken.kind) && astIsLeftHandSideExpression((expr as AstBinaryExpression).data.left); } return false; } function containsNarrowableReference(expr: Expression): boolean { - return isNarrowableReference(expr) || isOptionalChain(expr) && containsNarrowableReference(expr.expression); + return isNarrowableReference(expr.ast) || isOptionalChain(expr) && containsNarrowableReference(expr.expression); } function hasNarrowableArgument(expr: CallExpression) { @@ -1796,7 +1865,7 @@ function createBinder(): (file: SourceFile, options: CompilerOptions) => void { } function bindAssignmentTargetFlow(node: Expression) { - if (isNarrowableReference(node)) { + if (isNarrowableReference(node.ast)) { currentFlow = createFlowMutation(FlowFlags.Assignment, currentFlow, node); } else if (node.kind === SyntaxKind.ArrayLiteralExpression) { @@ -1906,7 +1975,7 @@ function createBinder(): (file: SourceFile, options: CompilerOptions) => void { // `bindBinaryExpressionFlow` will already have done this work. setParent(node, parent); const saveInStrictMode = inStrictMode; - bindWorker(node); + bindWorker(node.ast); const saveParent = parent; parent = node; state.skip = false; @@ -2252,7 +2321,7 @@ function createBinder(): (file: SourceFile, options: CompilerOptions) => void { return declareClassMember(node, symbolFlags, symbolExcludes); case SyntaxKind.EnumDeclaration: - return declareSymbol(container.symbol.exports!, container.symbol, node, symbolFlags, symbolExcludes); + return declareSymbol(container.symbol.exports!, container.symbol, node.ast, symbolFlags, symbolExcludes); case SyntaxKind.TypeLiteral: case SyntaxKind.JSDocTypeLiteral: @@ -2264,7 +2333,7 @@ function createBinder(): (file: SourceFile, options: CompilerOptions) => void { // container, and are never in scope otherwise (even inside the body of the // object / type / interface declaring them). An exception is type parameters, // which are in scope without qualification (similar to 'locals'). - return declareSymbol(container.symbol.members!, container.symbol, node, symbolFlags, symbolExcludes); + return declareSymbol(container.symbol.members!, container.symbol, node.ast, symbolFlags, symbolExcludes); case SyntaxKind.FunctionType: case SyntaxKind.ConstructorType: @@ -2291,20 +2360,20 @@ function createBinder(): (file: SourceFile, options: CompilerOptions) => void { // 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); + return declareSymbol(container.locals!, /*parent*/ undefined, node.ast, symbolFlags, symbolExcludes); } } function declareClassMember(node: Declaration, symbolFlags: SymbolFlags, symbolExcludes: SymbolFlags) { return isStatic(node) - ? declareSymbol(container.symbol.exports!, container.symbol, node, symbolFlags, symbolExcludes) - : declareSymbol(container.symbol.members!, container.symbol, node, symbolFlags, symbolExcludes); + ? declareSymbol(container.symbol.exports!, container.symbol, node.ast, symbolFlags, symbolExcludes) + : declareSymbol(container.symbol.members!, container.symbol, node.ast, symbolFlags, symbolExcludes); } function declareSourceFileMember(node: Declaration, symbolFlags: SymbolFlags, symbolExcludes: SymbolFlags) { return isExternalModule(file) ? declareModuleMember(node, symbolFlags, symbolExcludes) - : declareSymbol(file.locals!, /*parent*/ undefined, node, symbolFlags, symbolExcludes); + : declareSymbol(file.locals!, /*parent*/ undefined, node.ast, symbolFlags, symbolExcludes); } function hasExportDeclarations(node: ModuleDeclaration | SourceFile): boolean { @@ -2408,14 +2477,14 @@ function createBinder(): (file: SourceFile, options: CompilerOptions) => void { return symbol; } - function bindBlockScopedDeclaration(node: Declaration, symbolFlags: SymbolFlags, symbolExcludes: SymbolFlags) { + function bindBlockScopedDeclaration(node: AstDeclaration, symbolFlags: SymbolFlags, symbolExcludes: SymbolFlags) { switch (blockScopeContainer.kind) { case SyntaxKind.ModuleDeclaration: - declareModuleMember(node, symbolFlags, symbolExcludes); + declareModuleMember(node.node, symbolFlags, symbolExcludes); // TODO(rbuckton): do not instantiate `.node` break; case SyntaxKind.SourceFile: if (isExternalOrCommonJsModule(container as SourceFile)) { - declareModuleMember(node, symbolFlags, symbolExcludes); + declareModuleMember(node.node, symbolFlags, symbolExcludes); // TODO(rbuckton): do not instantiate `.node` break; } // falls through @@ -2425,7 +2494,7 @@ function createBinder(): (file: SourceFile, options: CompilerOptions) => void { blockScopeContainer.locals = createSymbolTable(); addToContainerChain(blockScopeContainer); } - declareSymbol(blockScopeContainer.locals, /*parent*/ undefined, node, symbolFlags, symbolExcludes); + declareSymbol(blockScopeContainer.locals, /*parent*/ undefined, node, symbolFlags, symbolExcludes); // TODO(rbuckton): do not instantiate `.node` } } @@ -2484,7 +2553,7 @@ function createBinder(): (file: SourceFile, options: CompilerOptions) => void { } else if (isJSDocEnumTag(typeAlias) || !typeAlias.fullName || typeAlias.fullName.kind === SyntaxKind.Identifier) { parent = typeAlias.parent; - bindBlockScopedDeclaration(typeAlias, SymbolFlags.TypeAlias, SymbolFlags.TypeAliasExcludes); + bindBlockScopedDeclaration(typeAlias.ast, SymbolFlags.TypeAlias, SymbolFlags.TypeAliasExcludes); } else { bind(typeAlias.fullName); @@ -2529,16 +2598,16 @@ function createBinder(): (file: SourceFile, options: CompilerOptions) => void { // The binder visits every node in the syntax tree so it is a convenient place to perform a single localized // check for reserved words used as identifiers in strict mode code, as well as `yield` or `await` in // [Yield] or [Await] contexts, respectively. - function checkContextualIdentifier(node: Identifier) { + function checkContextualIdentifier(node: AstIdentifier) { // Report error only if there are no parse errors in file if ( !file.parseDiagnostics.length && !(node.flags & NodeFlags.Ambient) && !(node.flags & NodeFlags.JSDoc) && - !isIdentifierName(node) + !astIsIdentifierName(node) ) { // strict mode identifiers - const originalKeywordKind = identifierToKeywordKind(node); + const originalKeywordKind = astIdentifierToKeywordKind(node); if (originalKeywordKind === undefined) { return; } @@ -2548,18 +2617,18 @@ function createBinder(): (file: SourceFile, options: CompilerOptions) => void { originalKeywordKind >= SyntaxKind.FirstFutureReservedWord && originalKeywordKind <= SyntaxKind.LastFutureReservedWord ) { - file.bindDiagnostics.push(createDiagnosticForNode(node, getStrictModeIdentifierMessage(node), declarationNameToString(node))); + file.bindDiagnostics.push(createDiagnosticForNode(node.node, getStrictModeIdentifierMessage(node.node), declarationNameToString(node.node))); // TODO(rbuckton): do not instantiate `.node` } else if (originalKeywordKind === SyntaxKind.AwaitKeyword) { - if (isExternalModule(file) && isInTopLevelContext(node)) { - file.bindDiagnostics.push(createDiagnosticForNode(node, Diagnostics.Identifier_expected_0_is_a_reserved_word_at_the_top_level_of_a_module, declarationNameToString(node))); + if (isExternalModule(file) && astIsInTopLevelContext(node)) { + file.bindDiagnostics.push(createDiagnosticForNode(node.node, Diagnostics.Identifier_expected_0_is_a_reserved_word_at_the_top_level_of_a_module, declarationNameToString(node.node))); // TODO(rbuckton): do not instantiate `.node` } else if (node.flags & NodeFlags.AwaitContext) { - file.bindDiagnostics.push(createDiagnosticForNode(node, Diagnostics.Identifier_expected_0_is_a_reserved_word_that_cannot_be_used_here, declarationNameToString(node))); + file.bindDiagnostics.push(createDiagnosticForNode(node.node, Diagnostics.Identifier_expected_0_is_a_reserved_word_that_cannot_be_used_here, declarationNameToString(node.node))); // TODO(rbuckton): do not instantiate `.node` } } else if (originalKeywordKind === SyntaxKind.YieldKeyword && node.flags & NodeFlags.YieldContext) { - file.bindDiagnostics.push(createDiagnosticForNode(node, Diagnostics.Identifier_expected_0_is_a_reserved_word_that_cannot_be_used_here, declarationNameToString(node))); + file.bindDiagnostics.push(createDiagnosticForNode(node.node, Diagnostics.Identifier_expected_0_is_a_reserved_word_that_cannot_be_used_here, declarationNameToString(node.node))); // TODO(rbuckton): do not instantiate `.node` } } } @@ -2580,11 +2649,11 @@ function createBinder(): (file: SourceFile, options: CompilerOptions) => void { // The binder visits every node, so this is a good place to check for // the reserved private name (there is only one) - function checkPrivateIdentifier(node: PrivateIdentifier) { - if (node.escapedText === "#constructor") { + function checkPrivateIdentifier(node: AstPrivateIdentifier) { + if (node.data.escapedText === "#constructor") { // Report error only if there are no parse errors in file if (!file.parseDiagnostics.length) { - file.bindDiagnostics.push(createDiagnosticForNode(node, Diagnostics.constructor_is_a_reserved_word, declarationNameToString(node))); + file.bindDiagnostics.push(createDiagnosticForNode(node.node, Diagnostics.constructor_is_a_reserved_word, declarationNameToString(node.node))); // TODO(rbuckton): do not instantiate `.node` } } } @@ -2768,7 +2837,7 @@ function createBinder(): (file: SourceFile, options: CompilerOptions) => void { // // However, not all symbols will end up in any of these tables. 'Anonymous' symbols // (like TypeLiterals for example) will not be put in any table. - bindWorker(node); + bindWorker(node.ast); // Then we recurse into the children of the node to bind them as well. For certain // symbols we do specialized work when we recurse. For example, we'll keep track of // the current 'container' node when it changes. This helps us know which symbol table @@ -2835,7 +2904,7 @@ function createBinder(): (file: SourceFile, options: CompilerOptions) => void { return nodeText === '"use strict"' || nodeText === "'use strict'"; } - function bindWorker(node: Node) { + function bindWorker(node: AstNode) { switch (node.kind) { /* Strict mode checks */ case SyntaxKind.Identifier: @@ -2844,77 +2913,80 @@ function createBinder(): (file: SourceFile, options: CompilerOptions) => void { // current "blockScopeContainer" needs to be set to its immediate namespace parent. if (node.flags & NodeFlags.IdentifierIsInJSDocNamespace) { let parentNode = node.parent; - while (parentNode && !isJSDocTypeAlias(parentNode)) { + while (parentNode && !astIsJSDocTypeAlias(parentNode)) { parentNode = parentNode.parent; } - bindBlockScopedDeclaration(parentNode as Declaration, SymbolFlags.TypeAlias, SymbolFlags.TypeAliasExcludes); + bindBlockScopedDeclaration(parentNode as AstDeclaration, SymbolFlags.TypeAlias, SymbolFlags.TypeAliasExcludes); break; } - // falls through + // TODO: Why use `isExpression` here? both Identifier and ThisKeyword are expressions. + if (currentFlow && (astIsExpression(node) || parent.kind === SyntaxKind.ShorthandPropertyAssignment)) { + astSetFlowNode(node as AstIdentifier, currentFlow); + } + return checkContextualIdentifier(node as AstIdentifier); case SyntaxKind.ThisKeyword: // TODO: Why use `isExpression` here? both Identifier and ThisKeyword are expressions. - if (currentFlow && (isExpression(node) || parent.kind === SyntaxKind.ShorthandPropertyAssignment)) { - (node as Identifier | ThisExpression).flowNode = currentFlow; + if (currentFlow && (astIsExpression(node) || parent.kind === SyntaxKind.ShorthandPropertyAssignment)) { + astSetFlowNode(node as AstThisExpression, currentFlow); } - // TODO: a `ThisExpression` is not an Identifier, this cast is unsound - return checkContextualIdentifier(node as Identifier); + return; case SyntaxKind.QualifiedName: - if (currentFlow && isPartOfTypeQuery(node)) { - (node as QualifiedName).flowNode = currentFlow; + if (currentFlow && astIsPartOfTypeQuery(node)) { + astSetFlowNode(node as AstQualifiedName, currentFlow); } break; case SyntaxKind.MetaProperty: case SyntaxKind.SuperKeyword: - (node as MetaProperty | SuperExpression).flowNode = currentFlow; + astSetFlowNode(node as AstMetaProperty | AstSuperExpression, currentFlow); break; case SyntaxKind.PrivateIdentifier: - return checkPrivateIdentifier(node as PrivateIdentifier); + return checkPrivateIdentifier(node as AstPrivateIdentifier); case SyntaxKind.PropertyAccessExpression: case SyntaxKind.ElementAccessExpression: - const expr = node as PropertyAccessExpression | ElementAccessExpression; + const expr = node as AstPropertyAccessExpression | AstElementAccessExpression; if (currentFlow && isNarrowableReference(expr)) { - expr.flowNode = currentFlow; + astSetFlowNode(expr, currentFlow); } - if (isSpecialPropertyDeclaration(expr)) { + if (astIsSpecialPropertyDeclaration(expr)) { bindSpecialPropertyDeclaration(expr); } if ( - isInJSFile(expr) && + astIsInJSFile(expr) && file.commonJsModuleIndicator && - isModuleExportsAccessExpression(expr) && + astIsModuleExportsAccessExpression(expr) && !lookupSymbolForName(blockScopeContainer, "module" as __String) ) { - declareSymbol(file.locals!, /*parent*/ undefined, expr.expression, SymbolFlags.FunctionScopedVariable | SymbolFlags.ModuleExports, SymbolFlags.FunctionScopedVariableExcludes); + declareSymbol(file.locals!, /*parent*/ undefined, astGetExpression(expr) as AstNode as AstDeclaration, SymbolFlags.FunctionScopedVariable | SymbolFlags.ModuleExports, SymbolFlags.FunctionScopedVariableExcludes); // TODO(rbuckton): do not instantiate `.node` } break; case SyntaxKind.BinaryExpression: - const specialKind = getAssignmentDeclarationKind(node as BinaryExpression); + const specialKind = astGetAssignmentDeclarationKind(node as AstBinaryExpression); switch (specialKind) { case AssignmentDeclarationKind.ExportsProperty: - bindExportsPropertyAssignment(node as BindableStaticPropertyAssignmentExpression); + bindExportsPropertyAssignment((node as AstBindableStaticPropertyAssignmentExpression).node); // TODO(rbuckton): do not instantiate `.node` break; case AssignmentDeclarationKind.ModuleExports: - bindModuleExportsAssignment(node as BindablePropertyAssignmentExpression); + bindModuleExportsAssignment((node as AstBindablePropertyAssignmentExpression).node); // TODO(rbuckton): do not instantiate `.node` break; case AssignmentDeclarationKind.PrototypeProperty: - bindPrototypePropertyAssignment((node as BindableStaticPropertyAssignmentExpression).left, node); + bindPrototypePropertyAssignment((node as AstBindableStaticPropertyAssignmentExpression).data.left.node, node.node); // TODO(rbuckton): do not instantiate `.node` break; case AssignmentDeclarationKind.Prototype: - bindPrototypeAssignment(node as BindableStaticPropertyAssignmentExpression); + bindPrototypeAssignment((node as AstBindableStaticPropertyAssignmentExpression).node); // TODO(rbuckton): do not instantiate `.node` break; case AssignmentDeclarationKind.ThisProperty: - bindThisPropertyAssignment(node as BindablePropertyAssignmentExpression); + bindThisPropertyAssignment((node as AstBindablePropertyAssignmentExpression).node); // TODO(rbuckton): do not instantiate `.node` break; case AssignmentDeclarationKind.Property: - const expression = ((node as BinaryExpression).left as AccessExpression).expression; - if (isInJSFile(node) && isIdentifier(expression)) { - const symbol = lookupSymbolForName(blockScopeContainer, expression.escapedText); - if (isThisInitializedDeclaration(symbol?.valueDeclaration)) { - bindThisPropertyAssignment(node as BindablePropertyAssignmentExpression); + const expression = ((node as AstBinaryExpression).data.left as AstAccessExpression).data.expression; + if (astIsInJSFile(node) && astIsIdentifier(expression)) { + const symbol = lookupSymbolForName(blockScopeContainer, expression.data.escapedText); + if (isThisInitializedDeclaration(symbol?.valueDeclaration)) { // TODO(rbuckton): ast variant of `valueDeclaration` + bindThisPropertyAssignment((node as AstBindablePropertyAssignmentExpression).node); // TODO(rbuckton): do not instantiate `.node` break; } } - bindSpecialPropertyAssignment(node as BindablePropertyAssignmentExpression); + bindSpecialPropertyAssignment((node as AstBindablePropertyAssignmentExpression).node); // TODO(rbuckton): do not instantiate `.node` break; case AssignmentDeclarationKind.None: // Nothing to do @@ -2922,94 +2994,94 @@ function createBinder(): (file: SourceFile, options: CompilerOptions) => void { default: Debug.fail("Unknown binary expression special property assignment kind"); } - return checkStrictModeBinaryExpression(node as BinaryExpression); + return checkStrictModeBinaryExpression((node as AstBinaryExpression).node); case SyntaxKind.CatchClause: - return checkStrictModeCatchClause(node as CatchClause); + return checkStrictModeCatchClause((node as AstCatchClause).node); case SyntaxKind.DeleteExpression: - return checkStrictModeDeleteExpression(node as DeleteExpression); + return checkStrictModeDeleteExpression((node as AstDeleteExpression).node); case SyntaxKind.PostfixUnaryExpression: - return checkStrictModePostfixUnaryExpression(node as PostfixUnaryExpression); + return checkStrictModePostfixUnaryExpression((node as AstPostfixUnaryExpression).node); case SyntaxKind.PrefixUnaryExpression: - return checkStrictModePrefixUnaryExpression(node as PrefixUnaryExpression); + return checkStrictModePrefixUnaryExpression((node as AstPrefixUnaryExpression).node); case SyntaxKind.WithStatement: - return checkStrictModeWithStatement(node as WithStatement); + return checkStrictModeWithStatement((node as AstWithStatement).node); case SyntaxKind.LabeledStatement: - return checkStrictModeLabeledStatement(node as LabeledStatement); + return checkStrictModeLabeledStatement((node as AstLabeledStatement).node); case SyntaxKind.ThisType: seenThisKeyword = true; return; case SyntaxKind.TypePredicate: break; // Binding the children will handle everything case SyntaxKind.TypeParameter: - return bindTypeParameter(node as TypeParameterDeclaration); + return bindTypeParameter((node as AstTypeParameterDeclaration).node); case SyntaxKind.Parameter: - return bindParameter(node as ParameterDeclaration); + return bindParameter((node as AstParameterDeclaration).node); case SyntaxKind.VariableDeclaration: - return bindVariableDeclarationOrBindingElement(node as VariableDeclaration); + return bindVariableDeclarationOrBindingElement((node as AstVariableDeclaration).node); case SyntaxKind.BindingElement: - (node as BindingElement).flowNode = currentFlow; - return bindVariableDeclarationOrBindingElement(node as BindingElement); + astSetFlowNode(node as AstBindingElement, currentFlow); + return bindVariableDeclarationOrBindingElement((node as AstBindingElement).node); case SyntaxKind.PropertyDeclaration: case SyntaxKind.PropertySignature: - return bindPropertyWorker(node as PropertyDeclaration | PropertySignature); + return bindPropertyWorker((node as AstPropertyDeclaration | AstPropertySignature).node); case SyntaxKind.PropertyAssignment: case SyntaxKind.ShorthandPropertyAssignment: - return bindPropertyOrMethodOrAccessor(node as Declaration, SymbolFlags.Property, SymbolFlags.PropertyExcludes); + return bindPropertyOrMethodOrAccessor((node as AstDeclaration).node, SymbolFlags.Property, SymbolFlags.PropertyExcludes); case SyntaxKind.EnumMember: - return bindPropertyOrMethodOrAccessor(node as Declaration, SymbolFlags.EnumMember, SymbolFlags.EnumMemberExcludes); + return bindPropertyOrMethodOrAccessor((node as AstDeclaration).node, SymbolFlags.EnumMember, SymbolFlags.EnumMemberExcludes); case SyntaxKind.CallSignature: case SyntaxKind.ConstructSignature: case SyntaxKind.IndexSignature: - return declareSymbolAndAddToSymbolTable(node as Declaration, SymbolFlags.Signature, SymbolFlags.None); + return declareSymbolAndAddToSymbolTable((node as AstDeclaration).node, SymbolFlags.Signature, SymbolFlags.None); case SyntaxKind.MethodDeclaration: case SyntaxKind.MethodSignature: // If this is an ObjectLiteralExpression method, then it sits in the same space // as other properties in the object literal. So we use SymbolFlags.PropertyExcludes // so that it will conflict with any other object literal members with the same // name. - return bindPropertyOrMethodOrAccessor(node as Declaration, SymbolFlags.Method | ((node as MethodDeclaration).questionToken ? SymbolFlags.Optional : SymbolFlags.None), isObjectLiteralMethod(node) ? SymbolFlags.PropertyExcludes : SymbolFlags.MethodExcludes); + return bindPropertyOrMethodOrAccessor((node as AstDeclaration).node, SymbolFlags.Method | (((node as AstMethodDeclaration).node).questionToken ? SymbolFlags.Optional : SymbolFlags.None), isObjectLiteralMethod(node.node) ? SymbolFlags.PropertyExcludes : SymbolFlags.MethodExcludes); // TODO(rbuckton): do not instantiate `.node` case SyntaxKind.FunctionDeclaration: - return bindFunctionDeclaration(node as FunctionDeclaration); + return bindFunctionDeclaration((node as AstFunctionDeclaration).node); case SyntaxKind.Constructor: - return declareSymbolAndAddToSymbolTable(node as Declaration, SymbolFlags.Constructor, /*symbolExcludes:*/ SymbolFlags.None); + return declareSymbolAndAddToSymbolTable((node as AstDeclaration).node, SymbolFlags.Constructor, /*symbolExcludes:*/ SymbolFlags.None); case SyntaxKind.GetAccessor: - return bindPropertyOrMethodOrAccessor(node as Declaration, SymbolFlags.GetAccessor, SymbolFlags.GetAccessorExcludes); + return bindPropertyOrMethodOrAccessor((node as AstDeclaration).node, SymbolFlags.GetAccessor, SymbolFlags.GetAccessorExcludes); case SyntaxKind.SetAccessor: - return bindPropertyOrMethodOrAccessor(node as Declaration, SymbolFlags.SetAccessor, SymbolFlags.SetAccessorExcludes); + return bindPropertyOrMethodOrAccessor((node as AstDeclaration).node, SymbolFlags.SetAccessor, SymbolFlags.SetAccessorExcludes); case SyntaxKind.FunctionType: case SyntaxKind.JSDocFunctionType: case SyntaxKind.JSDocSignature: case SyntaxKind.ConstructorType: - return bindFunctionOrConstructorType(node as SignatureDeclaration | JSDocSignature); + return bindFunctionOrConstructorType((node as AstSignatureDeclaration | AstJSDocSignature).node); // TODO(rbuckton): do not instantiate `.node` case SyntaxKind.TypeLiteral: case SyntaxKind.JSDocTypeLiteral: case SyntaxKind.MappedType: - return bindAnonymousTypeWorker(node as TypeLiteralNode | MappedTypeNode | JSDocTypeLiteral); + return bindAnonymousTypeWorker((node as AstTypeLiteralNode | AstMappedTypeNode | AstJSDocTypeLiteral).node); // TODO(rbuckton): do not instantiate `.node` case SyntaxKind.JSDocClassTag: - return bindJSDocClassTag(node as JSDocClassTag); + return bindJSDocClassTag((node as AstJSDocClassTag).node); // TODO(rbuckton): do not instantiate `.node` case SyntaxKind.ObjectLiteralExpression: - return bindObjectLiteralExpression(node as ObjectLiteralExpression); + return bindObjectLiteralExpression((node as AstObjectLiteralExpression).node); // TODO(rbuckton): do not instantiate `.node` case SyntaxKind.FunctionExpression: case SyntaxKind.ArrowFunction: - return bindFunctionExpression(node as FunctionExpression | ArrowFunction); + return bindFunctionExpression((node as AstFunctionExpression | AstArrowFunction).node); // TODO(rbuckton): do not instantiate `.node` case SyntaxKind.CallExpression: - const assignmentKind = getAssignmentDeclarationKind(node as CallExpression); + const assignmentKind = getAssignmentDeclarationKind((node as AstCallExpression).node); // TODO(rbuckton): do not instantiate `.node` switch (assignmentKind) { case AssignmentDeclarationKind.ObjectDefinePropertyValue: - return bindObjectDefinePropertyAssignment(node as BindableObjectDefinePropertyCall); + return bindObjectDefinePropertyAssignment((node as AstBindableObjectDefinePropertyCall).node); // TODO(rbuckton): do not instantiate `.node` case AssignmentDeclarationKind.ObjectDefinePropertyExports: - return bindObjectDefinePropertyExport(node as BindableObjectDefinePropertyCall); + return bindObjectDefinePropertyExport((node as AstBindableObjectDefinePropertyCall).node); // TODO(rbuckton): do not instantiate `.node` case AssignmentDeclarationKind.ObjectDefinePrototypeProperty: - return bindObjectDefinePrototypeProperty(node as BindableObjectDefinePropertyCall); + return bindObjectDefinePrototypeProperty((node as AstBindableObjectDefinePropertyCall).node); // TODO(rbuckton): do not instantiate `.node` case AssignmentDeclarationKind.None: break; // Nothing to do default: return Debug.fail("Unknown call expression assignment declaration kind"); } - if (isInJSFile(node)) { - bindCallExpression(node as CallExpression); + if (astIsInJSFile(node)) { + bindCallExpression((node as AstCallExpression).node); // TODO(rbuckton): do not instantiate `.node` } break; @@ -3018,68 +3090,68 @@ function createBinder(): (file: SourceFile, options: CompilerOptions) => void { case SyntaxKind.ClassDeclaration: // All classes are automatically in strict mode in ES6. inStrictMode = true; - return bindClassLikeDeclaration(node as ClassLikeDeclaration); + return bindClassLikeDeclaration((node as AstClassLikeDeclaration).node); // TODO(rbuckton): do not instantiate `.node` case SyntaxKind.InterfaceDeclaration: - return bindBlockScopedDeclaration(node as Declaration, SymbolFlags.Interface, SymbolFlags.InterfaceExcludes); + return bindBlockScopedDeclaration(node as AstDeclaration, SymbolFlags.Interface, SymbolFlags.InterfaceExcludes); // TODO(rbuckton): do not instantiate `.node` case SyntaxKind.TypeAliasDeclaration: - return bindBlockScopedDeclaration(node as Declaration, SymbolFlags.TypeAlias, SymbolFlags.TypeAliasExcludes); + return bindBlockScopedDeclaration(node as AstDeclaration, SymbolFlags.TypeAlias, SymbolFlags.TypeAliasExcludes); // TODO(rbuckton): do not instantiate `.node` case SyntaxKind.EnumDeclaration: - return bindEnumDeclaration(node as EnumDeclaration); + return bindEnumDeclaration((node as AstEnumDeclaration).node); // TODO(rbuckton): do not instantiate `.node` case SyntaxKind.ModuleDeclaration: - return bindModuleDeclaration(node as ModuleDeclaration); + return bindModuleDeclaration((node as AstModuleDeclaration).node); // TODO(rbuckton): do not instantiate `.node` // Jsx-attributes case SyntaxKind.JsxAttributes: - return bindJsxAttributes(node as JsxAttributes); + return bindJsxAttributes((node as AstJsxAttributes).node); // TODO(rbuckton): do not instantiate `.node` case SyntaxKind.JsxAttribute: - return bindJsxAttribute(node as JsxAttribute, SymbolFlags.Property, SymbolFlags.PropertyExcludes); + return bindJsxAttribute((node as AstJsxAttribute).node, SymbolFlags.Property, SymbolFlags.PropertyExcludes); // TODO(rbuckton): do not instantiate `.node` // Imports and exports case SyntaxKind.ImportEqualsDeclaration: case SyntaxKind.NamespaceImport: case SyntaxKind.ImportSpecifier: case SyntaxKind.ExportSpecifier: - return declareSymbolAndAddToSymbolTable(node as Declaration, SymbolFlags.Alias, SymbolFlags.AliasExcludes); + return declareSymbolAndAddToSymbolTable((node as AstDeclaration).node, SymbolFlags.Alias, SymbolFlags.AliasExcludes); // TODO(rbuckton): do not instantiate `.node` case SyntaxKind.NamespaceExportDeclaration: - return bindNamespaceExportDeclaration(node as NamespaceExportDeclaration); + return bindNamespaceExportDeclaration((node as AstNamespaceExportDeclaration).node); // TODO(rbuckton): do not instantiate `.node` case SyntaxKind.ImportClause: - return bindImportClause(node as ImportClause); + return bindImportClause((node as AstImportClause).node); // TODO(rbuckton): do not instantiate `.node` case SyntaxKind.ExportDeclaration: - return bindExportDeclaration(node as ExportDeclaration); + return bindExportDeclaration((node as AstExportDeclaration).node); // TODO(rbuckton): do not instantiate `.node` case SyntaxKind.ExportAssignment: - return bindExportAssignment(node as ExportAssignment); + return bindExportAssignment((node as AstExportAssignment).node); // TODO(rbuckton): do not instantiate `.node` case SyntaxKind.SourceFile: - updateStrictModeStatementList((node as SourceFile).statements); + updateStrictModeStatementList((node as AstSourceFile).data.statements.nodes); // TODO(rbuckton): do not instantiate `.nodes` return bindSourceFileIfExternalModule(); case SyntaxKind.Block: - if (!isFunctionLikeOrClassStaticBlockDeclaration(node.parent)) { + if (!isFunctionLikeOrClassStaticBlockDeclaration(node.parent?.node)) { // TODO(rbuckton): do not instantiate `.node` return; } // falls through case SyntaxKind.ModuleBlock: - return updateStrictModeStatementList((node as Block | ModuleBlock).statements); + return updateStrictModeStatementList((node as AstBlock | AstModuleBlock).data.statements.nodes); // TODO(rbuckton): do not instantiate `.nodes` case SyntaxKind.JSDocParameterTag: if (node.parent.kind === SyntaxKind.JSDocSignature) { - return bindParameter(node as JSDocParameterTag); + return bindParameter((node as AstJSDocParameterTag).node); // TODO(rbuckton): do not instantiate `.node` } if (node.parent.kind !== SyntaxKind.JSDocTypeLiteral) { break; } // falls through case SyntaxKind.JSDocPropertyTag: - const propTag = node as JSDocPropertyLikeTag; - const flags = propTag.isBracketed || propTag.typeExpression && propTag.typeExpression.type.kind === SyntaxKind.JSDocOptionalType ? + const propTag = node as AstJSDocPropertyLikeTag; + const flags = propTag.data.isBracketed || propTag.data.typeExpression && propTag.data.typeExpression.data.type.kind === SyntaxKind.JSDocOptionalType ? SymbolFlags.Property | SymbolFlags.Optional : SymbolFlags.Property; - return declareSymbolAndAddToSymbolTable(propTag, flags, SymbolFlags.PropertyExcludes); + return declareSymbolAndAddToSymbolTable(propTag.node, flags, SymbolFlags.PropertyExcludes); // TODO(rbuckton): do not instantiate `.node` case SyntaxKind.JSDocTypedefTag: case SyntaxKind.JSDocCallbackTag: case SyntaxKind.JSDocEnumTag: - return (delayedTypeAliases || (delayedTypeAliases = [])).push(node as JSDocTypedefTag | JSDocCallbackTag | JSDocEnumTag); + return (delayedTypeAliases || (delayedTypeAliases = [])).push((node as AstJSDocTypedefTag | AstJSDocCallbackTag | AstJSDocEnumTag).node); // TODO(rbuckton): do not instantiate `.node` case SyntaxKind.JSDocOverloadTag: - return bind((node as JSDocOverloadTag).typeExpression); + return bind((node as AstJSDocOverloadTag).data.typeExpression.node); // TODO(rbuckton): do not instantiate `.node` case SyntaxKind.JSDocImportTag: - return (jsDocImports || (jsDocImports = [])).push(node as JSDocImportTag); + return (jsDocImports || (jsDocImports = [])).push((node as AstJSDocImportTag).node); // TODO(rbuckton): do not instantiate `.node` } } @@ -3103,7 +3175,7 @@ function createBinder(): (file: SourceFile, options: CompilerOptions) => void { bindSourceFileAsExternalModule(); // Create symbol equivalent for the module.exports = {} const originalSymbol = file.symbol; - declareSymbol(file.symbol.exports!, file.symbol, file, SymbolFlags.Property, SymbolFlags.All); + declareSymbol(file.symbol.exports!, file.symbol, file.ast, SymbolFlags.Property, SymbolFlags.All); file.symbol = originalSymbol; } } @@ -3125,7 +3197,7 @@ function createBinder(): (file: SourceFile, options: CompilerOptions) => void { : SymbolFlags.Property; // If there is an `export default x;` alias declaration, can't `export default` anything else. // (In contrast, you can still have `export default function f() {}` and `export default interface I {}`.) - const symbol = declareSymbol(container.symbol.exports, container.symbol, node, flags, SymbolFlags.All); + const symbol = declareSymbol(container.symbol.exports, container.symbol, node.ast, flags, SymbolFlags.All); if (node.isExportEquals) { // Will be an error later, since the module already has other exports. Just make sure this has a valueDeclaration set. @@ -3147,7 +3219,7 @@ function createBinder(): (file: SourceFile, options: CompilerOptions) => void { } else { file.symbol.globalExports = file.symbol.globalExports || createSymbolTable(); - declareSymbol(file.symbol.globalExports, file.symbol, node, SymbolFlags.Alias, SymbolFlags.AliasExcludes); + declareSymbol(file.symbol.globalExports, file.symbol, node.ast, SymbolFlags.Alias, SymbolFlags.AliasExcludes); } } @@ -3158,13 +3230,13 @@ function createBinder(): (file: SourceFile, options: CompilerOptions) => void { } else if (!node.exportClause) { // All export * declarations are collected in an __export symbol - declareSymbol(container.symbol.exports, container.symbol, node, SymbolFlags.ExportStar, SymbolFlags.None); + declareSymbol(container.symbol.exports, container.symbol, node.ast, SymbolFlags.ExportStar, SymbolFlags.None); } else if (isNamespaceExport(node.exportClause)) { // declareSymbol walks up parents to find name text, parent _must_ be set // but won't be set by the normal binder walk until `bindChildren` later on. setParent(node.exportClause, node); - declareSymbol(container.symbol.exports, container.symbol, node.exportClause, SymbolFlags.Alias, SymbolFlags.AliasExcludes); + declareSymbol(container.symbol.exports, container.symbol, node.exportClause.ast, SymbolFlags.Alias, SymbolFlags.AliasExcludes); } } @@ -3199,7 +3271,7 @@ function createBinder(): (file: SourceFile, options: CompilerOptions) => void { }); if (symbol) { const flags = SymbolFlags.Property | SymbolFlags.ExportValue; - declareSymbol(symbol.exports!, symbol, node, flags, SymbolFlags.None); + declareSymbol(symbol.exports!, symbol, node.ast, flags, SymbolFlags.None); } } @@ -3219,7 +3291,7 @@ function createBinder(): (file: SourceFile, options: CompilerOptions) => void { const isAlias = isAliasableExpression(node.right) && (isExportsIdentifier(node.left.expression) || isModuleExportsAccessExpression(node.left.expression)); const flags = isAlias ? SymbolFlags.Alias : SymbolFlags.Property | SymbolFlags.ExportValue; setParent(node.left, node); - declareSymbol(symbol.exports!, symbol, node.left, flags, SymbolFlags.None); + declareSymbol(symbol.exports!, symbol, node.left.ast, flags, SymbolFlags.None); } } @@ -3245,12 +3317,12 @@ function createBinder(): (file: SourceFile, options: CompilerOptions) => void { const flags = exportAssignmentIsAlias(node) ? SymbolFlags.Alias // An export= with an EntityNameExpression or a ClassExpression exports all meanings of that identifier or class : SymbolFlags.Property | SymbolFlags.ExportValue | SymbolFlags.ValueModule; - const symbol = declareSymbol(file.symbol.exports!, file.symbol, node, flags | SymbolFlags.Assignment, SymbolFlags.None); + const symbol = declareSymbol(file.symbol.exports!, file.symbol, node.ast, flags | SymbolFlags.Assignment, SymbolFlags.None); setValueDeclaration(symbol, node); } function bindExportAssignedObjectMemberAlias(node: ShorthandPropertyAssignment) { - declareSymbol(file.symbol.exports!, file.symbol, node, SymbolFlags.Alias | SymbolFlags.Assignment, SymbolFlags.None); + declareSymbol(file.symbol.exports!, file.symbol, node.ast, SymbolFlags.Alias | SymbolFlags.Assignment, SymbolFlags.None); } function bindThisPropertyAssignment(node: BindablePropertyAssignmentExpression | PropertyAccessExpression | LiteralLikeElementAccessExpression) { @@ -3282,7 +3354,7 @@ function createBinder(): (file: SourceFile, options: CompilerOptions) => void { bindDynamicallyNamedThisPropertyAssignment(node, constructorSymbol, constructorSymbol.members); } else { - declareSymbol(constructorSymbol.members, constructorSymbol, node, SymbolFlags.Property | SymbolFlags.Assignment, SymbolFlags.PropertyExcludes & ~SymbolFlags.Property); + declareSymbol(constructorSymbol.members, constructorSymbol, node.ast, SymbolFlags.Property | SymbolFlags.Assignment, SymbolFlags.PropertyExcludes & ~SymbolFlags.Property); } addDeclarationToSymbol(constructorSymbol, constructorSymbol.valueDeclaration, SymbolFlags.Class); } @@ -3302,7 +3374,7 @@ function createBinder(): (file: SourceFile, options: CompilerOptions) => void { bindDynamicallyNamedThisPropertyAssignment(node, containingClass.symbol, symbolTable); } else { - declareSymbol(symbolTable, containingClass.symbol, node, SymbolFlags.Property | SymbolFlags.Assignment, SymbolFlags.None, /*isReplaceableByMethod*/ true); + declareSymbol(symbolTable, containingClass.symbol, node.ast, SymbolFlags.Property | SymbolFlags.Assignment, SymbolFlags.None, /*isReplaceableByMethod*/ true); } break; case SyntaxKind.SourceFile: @@ -3311,7 +3383,7 @@ function createBinder(): (file: SourceFile, options: CompilerOptions) => void { break; } else if (thisContainer.commonJsModuleIndicator) { - declareSymbol(thisContainer.symbol.exports!, thisContainer.symbol, node, SymbolFlags.Property | SymbolFlags.ExportValue, SymbolFlags.None); + declareSymbol(thisContainer.symbol.exports!, thisContainer.symbol, node.ast, SymbolFlags.Property | SymbolFlags.ExportValue, SymbolFlags.None); } else { declareSymbolAndAddToSymbolTable(node, SymbolFlags.FunctionScopedVariable, SymbolFlags.FunctionScopedVariableExcludes); @@ -3326,7 +3398,7 @@ function createBinder(): (file: SourceFile, options: CompilerOptions) => void { } function bindDynamicallyNamedThisPropertyAssignment(node: BinaryExpression | DynamicNamedDeclaration, symbol: Symbol, symbolTable: SymbolTable) { - declareSymbol(symbolTable, symbol, node, SymbolFlags.Property, SymbolFlags.None, /*isReplaceableByMethod*/ true, /*isComputedName*/ true); + declareSymbol(symbolTable, symbol, node.ast, SymbolFlags.Property, SymbolFlags.None, /*isReplaceableByMethod*/ true, /*isComputedName*/ true); addLateBoundAssignmentDeclarationToSymbol(node, symbol); } @@ -3336,16 +3408,16 @@ function createBinder(): (file: SourceFile, options: CompilerOptions) => void { } } - function bindSpecialPropertyDeclaration(node: PropertyAccessExpression | LiteralLikeElementAccessExpression) { - if (node.expression.kind === SyntaxKind.ThisKeyword) { - bindThisPropertyAssignment(node); + function bindSpecialPropertyDeclaration(node: AstPropertyAccessExpression | AstLiteralLikeElementAccessExpression) { + if (node.data.expression.kind === SyntaxKind.ThisKeyword) { + bindThisPropertyAssignment(node.node); // TODO(rbuckton): do not instantiate `.node` } - else if (isBindableStaticAccessExpression(node) && node.parent.parent.kind === SyntaxKind.SourceFile) { - if (isPrototypeAccess(node.expression)) { - bindPrototypePropertyAssignment(node, node.parent); + else if (astIsBindableStaticAccessExpression(node) && node.parent.parent.kind === SyntaxKind.SourceFile) { + if (astIsPrototypeAccess(node.data.expression)) { + bindPrototypePropertyAssignment(node.node, node.parent.node); // TODO(rbuckton): do not instantiate `.node` } else { - bindStaticPropertyAssignment(node); + bindStaticPropertyAssignment(node.node); // TODO(rbuckton): do not instantiate `.node` } } } @@ -3446,7 +3518,7 @@ function createBinder(): (file: SourceFile, options: CompilerOptions) => void { else { const table = parent ? parent.exports! : file.jsGlobalAugmentations || (file.jsGlobalAugmentations = createSymbolTable()); - return declareSymbol(table, parent, id, flags, excludeFlags); + return declareSymbol(table, parent, id.ast, flags, excludeFlags); } }); } @@ -3502,7 +3574,7 @@ function createBinder(): (file: SourceFile, options: CompilerOptions) => void { excludes = SymbolFlags.PropertyExcludes; } - declareSymbol(symbolTable, namespaceSymbol, declaration, includes | SymbolFlags.Assignment, excludes & ~SymbolFlags.Assignment); + declareSymbol(symbolTable, namespaceSymbol, declaration.ast, includes | SymbolFlags.Assignment, excludes & ~SymbolFlags.Assignment); } function isTopLevelNamespaceAssignment(propertyAccess: BindableAccessExpression) { @@ -3594,7 +3666,7 @@ function createBinder(): (file: SourceFile, options: CompilerOptions) => void { function bindClassLikeDeclaration(node: ClassLikeDeclaration) { if (node.kind === SyntaxKind.ClassDeclaration) { - bindBlockScopedDeclaration(node, SymbolFlags.Class, SymbolFlags.ClassExcludes); + bindBlockScopedDeclaration(node.ast, SymbolFlags.Class, SymbolFlags.ClassExcludes); } else { const bindingName = node.name ? node.name.escapedText : InternalSymbolName.Class; @@ -3630,8 +3702,8 @@ function createBinder(): (file: SourceFile, options: CompilerOptions) => void { function bindEnumDeclaration(node: EnumDeclaration) { return isEnumConst(node) - ? bindBlockScopedDeclaration(node, SymbolFlags.ConstEnum, SymbolFlags.ConstEnumExcludes) - : bindBlockScopedDeclaration(node, SymbolFlags.RegularEnum, SymbolFlags.RegularEnumExcludes); + ? bindBlockScopedDeclaration(node.ast, SymbolFlags.ConstEnum, SymbolFlags.ConstEnumExcludes) + : bindBlockScopedDeclaration(node.ast, SymbolFlags.RegularEnum, SymbolFlags.RegularEnumExcludes); } function bindVariableDeclarationOrBindingElement(node: VariableDeclaration | BindingElement) { @@ -3650,7 +3722,7 @@ function createBinder(): (file: SourceFile, options: CompilerOptions) => void { declareSymbolAndAddToSymbolTable(node as Declaration, SymbolFlags.Alias, SymbolFlags.AliasExcludes); } else if (isBlockOrCatchScoped(node)) { - bindBlockScopedDeclaration(node, SymbolFlags.BlockScopedVariable, SymbolFlags.BlockScopedVariableExcludes); + bindBlockScopedDeclaration(node.ast, SymbolFlags.BlockScopedVariable, SymbolFlags.BlockScopedVariableExcludes); } else if (isPartOfParameterDeclaration(node)) { // It is safe to walk up parent chain to find whether the node is a destructuring parameter declaration @@ -3691,7 +3763,7 @@ function createBinder(): (file: SourceFile, options: CompilerOptions) => void { // containing class. if (isParameterPropertyDeclaration(node, node.parent)) { const classDeclaration = node.parent.parent; - declareSymbol(classDeclaration.symbol.members!, classDeclaration.symbol, node, SymbolFlags.Property | (node.questionToken ? SymbolFlags.Optional : SymbolFlags.None), SymbolFlags.PropertyExcludes); + declareSymbol(classDeclaration.symbol.members!, classDeclaration.symbol, node.ast, SymbolFlags.Property | (node.questionToken ? SymbolFlags.Optional : SymbolFlags.None), SymbolFlags.PropertyExcludes); } } @@ -3705,7 +3777,7 @@ function createBinder(): (file: SourceFile, options: CompilerOptions) => void { checkStrictModeFunctionName(node); if (inStrictMode) { checkStrictModeFunctionDeclaration(node); - bindBlockScopedDeclaration(node, SymbolFlags.Function, SymbolFlags.FunctionExcludes); + bindBlockScopedDeclaration(node.ast, SymbolFlags.Function, SymbolFlags.FunctionExcludes); } else { declareSymbolAndAddToSymbolTable(node, SymbolFlags.Function, SymbolFlags.FunctionExcludes); @@ -3751,7 +3823,7 @@ function createBinder(): (file: SourceFile, options: CompilerOptions) => void { if (container) { Debug.assertNode(container, canHaveLocals); container.locals ??= createSymbolTable(); - declareSymbol(container.locals, /*parent*/ undefined, node, SymbolFlags.TypeParameter, SymbolFlags.TypeParameterExcludes); + declareSymbol(container.locals, /*parent*/ undefined, node.ast, SymbolFlags.TypeParameter, SymbolFlags.TypeParameterExcludes); } else { declareSymbolAndAddToSymbolTable(node, SymbolFlags.TypeParameter, SymbolFlags.TypeParameterExcludes); @@ -3762,7 +3834,7 @@ function createBinder(): (file: SourceFile, options: CompilerOptions) => void { if (container) { Debug.assertNode(container, canHaveLocals); container.locals ??= createSymbolTable(); - declareSymbol(container.locals, /*parent*/ undefined, node, SymbolFlags.TypeParameter, SymbolFlags.TypeParameterExcludes); + declareSymbol(container.locals, /*parent*/ undefined, node.ast, SymbolFlags.TypeParameter, SymbolFlags.TypeParameterExcludes); } else { bindAnonymousDeclaration(node, SymbolFlags.TypeParameter, getDeclarationName(node)!); // TODO: GH#18217 diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 2aa5e6c7afa..f9f990b0d07 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -1134,6 +1134,7 @@ import { hasName, canHaveQuestionToken, hasAsteriskToken, + AstDeclaration, } from "./_namespaces/ts.js"; import * as moduleSpecifiers from "./_namespaces/ts.moduleSpecifiers.js"; import * as performance from "./_namespaces/ts.performance.js"; @@ -1539,11 +1540,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { var globals = createSymbolTable(); var undefinedSymbol = createSymbol(SymbolFlags.Property, "undefined" as __String); - undefinedSymbol.declarations = []; + undefinedSymbol.astDeclarations = []; var globalThisSymbol = createSymbol(SymbolFlags.Module, "globalThis" as __String, CheckFlags.Readonly); globalThisSymbol.exports = globals; - globalThisSymbol.declarations = []; + globalThisSymbol.astDeclarations = []; globals.set(globalThisSymbol.escapedName, globalThisSymbol); var argumentsSymbol = createSymbol(SymbolFlags.Property, "arguments" as __String); @@ -2545,8 +2546,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return diagnostic; } - function addDeprecatedSuggestionWorker(declarations: Node | Node[], diagnostic: DiagnosticWithLocation) { - const deprecatedTag = Array.isArray(declarations) ? forEach(declarations, getJSDocDeprecatedTag) : getJSDocDeprecatedTag(declarations); + function addDeprecatedSuggestionWorker(declarations: Node | readonly Node[], diagnostic: DiagnosticWithLocation) { + const deprecatedTag = isArray(declarations) ? forEach(declarations, getJSDocDeprecatedTag) : getJSDocDeprecatedTag(declarations); if (deprecatedTag) { addRelatedInfo( diagnostic, @@ -2571,7 +2572,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return !!(getCombinedNodeFlagsCached(declaration) & NodeFlags.Deprecated); } - function addDeprecatedSuggestion(location: Node, declarations: Node[], deprecatedEntity: string) { + function addDeprecatedSuggestion(location: Node, declarations: readonly Node[], deprecatedEntity: string) { const diagnostic = createDiagnosticForNode(location, Diagnostics._0_is_deprecated, deprecatedEntity); return addDeprecatedSuggestionWorker(declarations, diagnostic); } @@ -2634,9 +2635,9 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { function cloneSymbol(symbol: Symbol): TransientSymbol { const result = createSymbol(symbol.flags, symbol.escapedName); - result.declarations = symbol.declarations ? symbol.declarations.slice() : []; + result.astDeclarations = symbol.astDeclarations ? symbol.astDeclarations.slice() : []; result.parent = symbol.parent; - if (symbol.valueDeclaration) result.valueDeclaration = symbol.valueDeclaration; + if (symbol.astValueDeclaration) result.astValueDeclaration = symbol.astValueDeclaration; if (symbol.constEnumOnlyModule) result.constEnumOnlyModule = true; if (symbol.members) result.members = new Map(symbol.members); if (symbol.exports) result.exports = new Map(symbol.exports); @@ -2683,7 +2684,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (source.valueDeclaration) { setValueDeclaration(target, source.valueDeclaration); } - addRange(target.declarations, source.declarations); + addRange(target.astDeclarations, source.astDeclarations); if (source.members) { if (!target.members) target.members = createSymbolTable(); mergeSymbolTable(target.members, source.members, unidirectional); @@ -3906,9 +3907,9 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } const result = createSymbol(valueSymbol.flags | typeSymbol.flags, valueSymbol.escapedName); Debug.assert(valueSymbol.declarations || typeSymbol.declarations); - result.declarations = deduplicate(concatenate(valueSymbol.declarations!, typeSymbol.declarations), equateValues); + result.astDeclarations = deduplicate(concatenate(valueSymbol.astDeclarations!, typeSymbol.astDeclarations), equateValues); result.parent = valueSymbol.parent || typeSymbol.parent; - if (valueSymbol.valueDeclaration) result.valueDeclaration = valueSymbol.valueDeclaration; + if (valueSymbol.astValueDeclaration) result.astValueDeclaration = valueSymbol.astValueDeclaration; if (typeSymbol.members) result.members = new Map(typeSymbol.members); if (valueSymbol.exports) result.exports = new Map(valueSymbol.exports); return result; @@ -4964,11 +4965,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { */ function cloneTypeAsModuleType(symbol: Symbol, moduleType: Type, referenceParent: ImportDeclaration | ImportCall) { const result = createSymbol(symbol.flags, symbol.escapedName); - result.declarations = symbol.declarations ? symbol.declarations.slice() : []; + result.astDeclarations = symbol.astDeclarations ? symbol.astDeclarations.slice() : []; result.parent = symbol.parent; result.links.target = symbol; result.links.originatingImport = referenceParent; - if (symbol.valueDeclaration) result.valueDeclaration = symbol.valueDeclaration; + if (symbol.astValueDeclaration) result.astValueDeclaration = symbol.astValueDeclaration; if (symbol.constEnumOnlyModule) result.constEnumOnlyModule = true; if (symbol.members) result.members = new Map(symbol.members); if (symbol.exports) result.exports = new Map(symbol.exports); @@ -9727,7 +9728,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { ); } - function getSomeTargetNameFromDeclarations(declarations: Declaration[] | undefined) { + function getSomeTargetNameFromDeclarations(declarations: readonly Declaration[] | undefined) { return firstDefined(declarations, d => { if (isImportSpecifier(d) || isExportSpecifier(d)) { return moduleExportNameTextUnescaped(d.propertyName || d.name); @@ -10729,7 +10730,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } return result; - function buildVisibleNodeList(declarations: Declaration[] | undefined) { + function buildVisibleNodeList(declarations: readonly Declaration[] | undefined) { forEach(declarations, declaration => { const resultNode = getAnyImportSyntax(declaration) || declaration; if (setVisibility) { @@ -11560,8 +11561,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } const union = createSymbol(s.flags | exportedMember.flags, name); union.links.type = getUnionType([getTypeOfSymbol(s), getTypeOfSymbol(exportedMember)]); - union.valueDeclaration = exportedMember.valueDeclaration; - union.declarations = concatenate(exportedMember.declarations, s.declarations); + union.astValueDeclaration = exportedMember.astValueDeclaration; + union.astDeclarations = concatenate(exportedMember.astDeclarations, s.astDeclarations); members.set(name, union); } else { @@ -11618,7 +11619,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { (thisContainer.kind === SyntaxKind.FunctionExpression && !isPrototypePropertyAssignment(thisContainer.parent)); } - function getConstructorDefinedThisAssignmentTypes(types: Type[], declarations: Declaration[]): Type[] | undefined { + function getConstructorDefinedThisAssignmentTypes(types: Type[], declarations: readonly Declaration[]): Type[] | undefined { Debug.assert(types.length === declarations.length); return types.filter((_, i) => { const declaration = declarations[i]; @@ -11846,10 +11847,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (symbol.flags & SymbolFlags.ModuleExports && symbol.valueDeclaration) { const fileSymbol = getSymbolOfDeclaration(getSourceFileOfNode(symbol.valueDeclaration)); const result = createSymbol(fileSymbol.flags, "exports" as __String); - result.declarations = fileSymbol.declarations ? fileSymbol.declarations.slice() : []; + result.astDeclarations = fileSymbol.astDeclarations ? fileSymbol.astDeclarations.slice() : []; result.parent = symbol; result.links.target = fileSymbol; - if (fileSymbol.valueDeclaration) result.valueDeclaration = fileSymbol.valueDeclaration; + if (fileSymbol.astValueDeclaration) result.astValueDeclaration = fileSymbol.astValueDeclaration; if (fileSymbol.members) result.members = new Map(fileSymbol.members); if (fileSymbol.exports) result.exports = new Map(fileSymbol.exports); const members = createSymbolTable(); @@ -13118,15 +13119,15 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { Debug.assert(!!(getCheckFlags(symbol) & CheckFlags.Late), "Expected a late-bound symbol."); symbol.flags |= symbolFlags; getSymbolLinks(member.symbol).lateSymbol = symbol; - if (!symbol.declarations) { - symbol.declarations = [member]; + if (!symbol.astDeclarations) { + symbol.astDeclarations = [member.ast]; } else if (!member.symbol.isReplaceableByMethod) { - symbol.declarations.push(member); + symbol.astDeclarations.push(member.ast); } if (symbolFlags & SymbolFlags.Value) { - if (!symbol.valueDeclaration || symbol.valueDeclaration.kind !== member.kind) { - symbol.valueDeclaration = member; + if (!symbol.astValueDeclaration || symbol.astValueDeclaration.kind !== member.kind) { + symbol.astValueDeclaration = member.ast; } } } @@ -13219,11 +13220,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // Then just add the computed name as a late bound declaration // (note: unlike `addDeclarationToLateBoundSymbol` we do not set up a `.lateSymbol` on `decl`'s links, // since that would point at an index symbol and not a single property symbol, like most consumers would expect) - if (!indexSymbol.declarations) { - indexSymbol.declarations = [decl]; + if (!indexSymbol.astDeclarations) { + indexSymbol.astDeclarations = [decl.ast]; } else if (!decl.symbol.isReplaceableByMethod) { - indexSymbol.declarations.push(decl); + indexSymbol.astDeclarations.push(decl.ast); } } @@ -14010,7 +14011,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } const checkFlags = CheckFlags.ReverseMapped | (readonlyMask && isReadonlySymbol(prop) ? CheckFlags.Readonly : 0); const inferredProp = createSymbol(SymbolFlags.Property | prop.flags & optionalMask, prop.escapedName, checkFlags) as ReverseMappedSymbol; - inferredProp.declarations = prop.declarations; + inferredProp.astDeclarations = prop.astDeclarations; inferredProp.links.nameType = getSymbolLinks(prop).nameType; inferredProp.links.propertyType = getTypeOfSymbol(prop); if ( @@ -14146,7 +14147,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { prop.links.keyType = keyType; if (modifiersProp) { prop.links.syntheticOrigin = modifiersProp; - prop.declarations = shouldLinkPropDeclarations ? modifiersProp.declarations : undefined; + prop.astDeclarations = shouldLinkPropDeclarations ? modifiersProp.astDeclarations : undefined; } members.set(propName, prop); } @@ -14948,7 +14949,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } } const props = propSet ? arrayFrom(propSet.values()) : [singleProp]; - let declarations: Declaration[] | undefined; + let declarations: AstDeclaration[] | undefined; let firstType: Type | undefined; let nameType: Type | undefined; const propTypes: Type[] = []; @@ -14962,7 +14963,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { else if (prop.valueDeclaration && prop.valueDeclaration !== firstValueDeclaration) { hasNonUniformValueDeclaration = true; } - declarations = addRange(declarations, prop.declarations); + declarations = addRange(declarations, prop.astDeclarations); const type = getTypeOfSymbol(prop); if (!firstType) { firstType = type; @@ -14987,7 +14988,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const result = createSymbol(SymbolFlags.Property | (optionalFlag ?? 0), name, syntheticFlag | checkFlags); result.links.containingType = containingType; if (!hasNonUniformValueDeclaration && firstValueDeclaration) { - result.valueDeclaration = firstValueDeclaration; + result.astValueDeclaration = firstValueDeclaration.ast; // Inherit information about parent type. if (firstValueDeclaration.symbol.parent) { @@ -14995,7 +14996,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } } - result.declarations = declarations; + result.astDeclarations = declarations; result.links.nameType = nameType; if (propTypes.length > 2) { // When `propTypes` has the potential to explode in size when normalized, defer normalization until absolutely needed @@ -15935,8 +15936,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // type variables by `couldContainTypeVariables` const type = createObjectType(ObjectFlags.Anonymous | ObjectFlags.SingleSignatureType, createSymbol(SymbolFlags.Function, InternalSymbolName.Function)) as SingleSignatureType; if (signature.declaration && !nodeIsSynthesized(signature.declaration)) { // skip synthetic declarations - keeping those around could be bad, since they lack a parent pointer - type.symbol.declarations = [signature.declaration]; - type.symbol.valueDeclaration = signature.declaration; + type.symbol.astDeclarations = [signature.declaration.ast]; + type.symbol.astValueDeclaration = signature.declaration.ast; } outerTypeParameters ||= signature.declaration && getOuterTypeParameters(signature.declaration, /*includeThisTypes*/ true); type.outerTypeParameters = outerTypeParameters; @@ -19424,7 +19425,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const flags = SymbolFlags.Property | SymbolFlags.Optional; const result = createSymbol(flags, prop.escapedName, getIsLateCheckFlag(prop) | (readonly ? CheckFlags.Readonly : 0)); result.links.type = isSetonlyAccessor ? undefinedType : addOptionality(getTypeOfSymbol(prop), /*isProperty*/ true); - result.declarations = prop.declarations; + result.astDeclarations = prop.astDeclarations; result.links.nameType = getSymbolLinks(prop).nameType; result.links.syntheticOrigin = prop; members.set(prop.escapedName, result); @@ -19508,7 +19509,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const rightProp = members.get(leftProp.escapedName)!; const rightType = getTypeOfSymbol(rightProp); if (rightProp.flags & SymbolFlags.Optional) { - const declarations = concatenate(leftProp.declarations, rightProp.declarations); + const declarations = concatenate(leftProp.astDeclarations, rightProp.astDeclarations); const flags = SymbolFlags.Property | (leftProp.flags & SymbolFlags.Optional); const result = createSymbol(flags, leftProp.escapedName); // Optimization: avoid calculating the union type if spreading into the exact same type. @@ -19521,7 +19522,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { result.links.type = leftTypeWithoutUndefined === rightTypeWithoutUndefined ? leftType : getUnionType([leftType, rightTypeWithoutUndefined], UnionReduction.Subtype); result.links.leftSpread = leftProp; result.links.rightSpread = rightProp; - result.declarations = declarations; + result.astDeclarations = declarations; result.links.nameType = getSymbolLinks(leftProp).nameType; members.set(leftProp.escapedName, result); } @@ -19551,7 +19552,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const flags = SymbolFlags.Property | (prop.flags & SymbolFlags.Optional); const result = createSymbol(flags, prop.escapedName, getIsLateCheckFlag(prop) | (readonly ? CheckFlags.Readonly : 0)); result.links.type = isSetonlyAccessor ? undefinedType : getTypeOfSymbol(prop); - result.declarations = prop.declarations; + result.astDeclarations = prop.astDeclarations; result.links.nameType = getSymbolLinks(prop).nameType; result.links.syntheticOrigin = prop; return result; @@ -20003,12 +20004,12 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // Keep the flags from the symbol we're instantiating. Mark that is instantiated, and // also transient so that we can just store data on it directly. const result = createSymbol(symbol.flags, symbol.escapedName, CheckFlags.Instantiated | getCheckFlags(symbol) & (CheckFlags.Readonly | CheckFlags.Late | CheckFlags.OptionalParameter | CheckFlags.RestParameter)); - result.declarations = symbol.declarations; + result.astDeclarations = symbol.astDeclarations; result.parent = symbol.parent; result.links.target = symbol; result.links.mapper = mapper; - if (symbol.valueDeclaration) { - result.valueDeclaration = symbol.valueDeclaration; + if (symbol.astValueDeclaration) { + result.astValueDeclaration = symbol.astValueDeclaration; } if (links.nameType) { result.links.nameType = links.nameType; @@ -20035,7 +20036,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { outerTypeParameters = addRange(outerTypeParameters, templateTagParameters); } typeParameters = outerTypeParameters || emptyArray; - const allDeclarations = type.objectFlags & (ObjectFlags.Reference | ObjectFlags.InstantiationExpressionType) ? [declaration] : type.symbol.declarations!; + const allDeclarations: readonly Node[] = type.objectFlags & (ObjectFlags.Reference | ObjectFlags.InstantiationExpressionType) ? [declaration] : type.symbol.declarations!; typeParameters = (target.objectFlags & (ObjectFlags.Reference | ObjectFlags.InstantiationExpressionType) || target.symbol.flags & SymbolFlags.Method || target.symbol.flags & SymbolFlags.TypeLiteral) && !target.aliasTypeArguments ? filter(typeParameters, tp => some(allDeclarations, d => isTypeParameterPossiblyReferenced(tp, d))) : typeParameters; @@ -25102,12 +25103,12 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { function createSymbolWithType(source: Symbol, type: Type | undefined) { const symbol = createSymbol(source.flags, source.escapedName, getCheckFlags(source) & CheckFlags.Readonly); - symbol.declarations = source.declarations; + symbol.astDeclarations = source.astDeclarations; symbol.parent = source.parent; symbol.links.type = type; symbol.links.target = source; - if (source.valueDeclaration) { - symbol.valueDeclaration = source.valueDeclaration; + if (source.astValueDeclaration) { + symbol.astValueDeclaration = source.astValueDeclaration; } const nameType = getSymbolLinks(source).nameType; if (nameType) { @@ -25647,8 +25648,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const literalProp = createSymbol(SymbolFlags.Property, name); literalProp.links.type = anyType; if (t.symbol) { - literalProp.declarations = t.symbol.declarations; - literalProp.valueDeclaration = t.symbol.valueDeclaration; + literalProp.astDeclarations = t.symbol.astDeclarations; + literalProp.astValueDeclaration = t.symbol.astValueDeclaration; } members.set(name, literalProp); }); @@ -32746,10 +32747,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } } - prop.declarations = member.declarations; + prop.astDeclarations = member.astDeclarations; prop.parent = member.parent; - if (member.valueDeclaration) { - prop.valueDeclaration = member.valueDeclaration; + if (member.astValueDeclaration) { + prop.astValueDeclaration = member.astValueDeclaration; } prop.links.type = type; @@ -32979,10 +32980,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { objectFlags |= getObjectFlags(exprType) & ObjectFlags.PropagatingFlags; const attributeSymbol = createSymbol(SymbolFlags.Property | member.flags, member.escapedName); - attributeSymbol.declarations = member.declarations; + attributeSymbol.astDeclarations = member.astDeclarations; attributeSymbol.parent = member.parent; - if (member.valueDeclaration) { - attributeSymbol.valueDeclaration = member.valueDeclaration; + if (member.astValueDeclaration) { + attributeSymbol.astValueDeclaration = member.astValueDeclaration; } attributeSymbol.links.type = exprType; attributeSymbol.links.target = member; @@ -33059,9 +33060,9 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { childrenContextualType && someType(childrenContextualType, isTupleLikeType) ? createTupleType(childrenTypes) : createArrayType(getUnionType(childrenTypes)); // Fake up a property declaration for the children - childrenPropSymbol.valueDeclaration = factory.createPropertySignature(/*modifiers*/ undefined, unescapeLeadingUnderscores(jsxChildrenPropertyName), /*questionToken*/ undefined, /*type*/ undefined); + childrenPropSymbol.astValueDeclaration = factory.createPropertySignature(/*modifiers*/ undefined, unescapeLeadingUnderscores(jsxChildrenPropertyName), /*questionToken*/ undefined, /*type*/ undefined).ast; setParent(childrenPropSymbol.valueDeclaration, attributeParent); - childrenPropSymbol.valueDeclaration.symbol = childrenPropSymbol; + childrenPropSymbol.valueDeclaration!.symbol = childrenPropSymbol; const childPropMap = createSymbolTable(); childPropMap.set(jsxChildrenPropertyName, childrenPropSymbol); spread = getSpreadType(spread, createAnonymousType(attributesSymbol, childPropMap, emptyArray, emptyArray, emptyArray), attributesSymbol, objectFlags, /*readonly*/ false); @@ -42095,7 +42096,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return implementationSharesContainerWithFirstOverload ? implementation : overloads[0]; } - function checkFlagAgreementBetweenOverloads(overloads: Declaration[], implementation: FunctionLikeDeclaration | undefined, flagsToCheck: ModifierFlags, someOverloadFlags: ModifierFlags, allOverloadFlags: ModifierFlags): void { + function checkFlagAgreementBetweenOverloads(overloads: readonly Declaration[], implementation: FunctionLikeDeclaration | undefined, flagsToCheck: ModifierFlags, someOverloadFlags: ModifierFlags, allOverloadFlags: ModifierFlags): void { // Error if some overloads have a flag that is not shared by all overloads. To find the // deviations, we XOR someOverloadFlags with allOverloadFlags const someButNotAllOverloadFlags = someOverloadFlags ^ allOverloadFlags; @@ -42135,7 +42136,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } } - function checkQuestionTokenAgreementBetweenOverloads(overloads: Declaration[], implementation: FunctionLikeDeclaration | undefined, someHaveQuestionToken: boolean, allHaveQuestionToken: boolean): void { + function checkQuestionTokenAgreementBetweenOverloads(overloads: readonly Declaration[], implementation: FunctionLikeDeclaration | undefined, someHaveQuestionToken: boolean, allHaveQuestionToken: boolean): void { if (someHaveQuestionToken !== allHaveQuestionToken) { const canonicalHasQuestionToken = hasQuestionToken(getCanonicalOverload(overloads, implementation)); forEach(overloads, o => { @@ -45732,7 +45733,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // and properties with literal names were already checked. if (!isStatic(member) && !hasBindableName(member)) { const symbol = getSymbolOfDeclaration(member); - checkIndexConstraintForProperty(type, symbol, getTypeOfExpression((member as DynamicNamedDeclaration).name.expression), getNonMissingTypeOfSymbol(symbol)); + checkIndexConstraintForProperty(type, symbol, getTypeOfExpression((member as NamedDeclaration as DynamicNamedDeclaration).name.expression), getNonMissingTypeOfSymbol(symbol)); } } } @@ -47964,7 +47965,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } } - function isDuplicatedCommonJSExport(declarations: Declaration[] | undefined) { + function isDuplicatedCommonJSExport(declarations: readonly Declaration[] | undefined) { return declarations && declarations.length > 1 && declarations.every(d => isInJSFile(d) && isAccessExpression(d) && (isExportsIdentifier(d.expression) || isModuleExportsAccessExpression(d.expression))); @@ -48982,8 +48983,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } else { const copy = createSymbol(SymbolFlags.Signature, InternalSymbolName.Index); - copy.declarations = mapDefined(infos, i => i.declaration); - copy.parent = type.aliasSymbol ? type.aliasSymbol : type.symbol ? type.symbol : getSymbolAtLocation(copy.declarations[0].parent); + copy.astDeclarations = mapDefined(infos, i => i.declaration?.ast); + copy.parent = type.aliasSymbol ? type.aliasSymbol : type.symbol ? type.symbol : getSymbolAtLocation(copy.astDeclarations[0].parent.node); symbolLinks.filteredIndexSymbolCache.set(nodeListId, copy); return copy; } @@ -50133,7 +50134,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return true; } return false; - }); + })?.slice(); } } } diff --git a/src/compiler/core.ts b/src/compiler/core.ts index ef83fefd533..565e875fe8f 100644 --- a/src/compiler/core.ts +++ b/src/compiler/core.ts @@ -10,6 +10,7 @@ import { SortedReadonlyArray, TextSpan, } from "./_namespaces/ts.js"; +import { ReadonlyArrayView } from "./readonlyArray.js"; /* eslint-disable @typescript-eslint/prefer-for-of */ @@ -1749,7 +1750,7 @@ export function createSet(getHashCode: (element: TElem */ export function isArray(value: any): value is readonly unknown[] { // See: https://github.com/microsoft/TypeScript/issues/17002 - return Array.isArray(value); + return Array.isArray(value) || ReadonlyArrayView.isReadonlyArrayView(value); } /** @internal */ @@ -2591,3 +2592,8 @@ export function isNodeLikeSystem(): boolean { && !(process as any).browser && typeof require !== "undefined"; } + +/** @internal */ +export function createReadOnlyArrayView(source: readonly T[], mapper: (value: T) => U): readonly U[] { + return new ReadonlyArrayView(source, mapper); +} \ No newline at end of file diff --git a/src/compiler/debug.ts b/src/compiler/debug.ts index d4c818a6c0c..b7d37321a6b 100644 --- a/src/compiler/debug.ts +++ b/src/compiler/debug.ts @@ -233,6 +233,8 @@ export namespace Debug { return fail(`${message} ${detail}`, stackCrawlMark || assertNever); } + export function assertNeverTypeOnly(_: never): void {} + export function assertEachNode(nodes: NodeArray, test: (node: T) => node is U, message?: string, stackCrawlMark?: AnyFunction): asserts nodes is NodeArray; export function assertEachNode(nodes: readonly T[], test: (node: T) => node is U, message?: string, stackCrawlMark?: AnyFunction): asserts nodes is readonly U[]; export function assertEachNode(nodes: NodeArray | undefined, test: (node: T) => node is U, message?: string, stackCrawlMark?: AnyFunction): asserts nodes is NodeArray | undefined; diff --git a/src/compiler/factory/astNodeFactory.ts b/src/compiler/factory/astNodeFactory.ts index 6a532abf960..d84b8fdfa84 100644 --- a/src/compiler/factory/astNodeFactory.ts +++ b/src/compiler/factory/astNodeFactory.ts @@ -293,22 +293,21 @@ import { getSyntheticLeadingComments, getSyntheticTrailingComments, identity, - isAstBinaryExpression, - isAstCallChain, - isAstCommaListExpression, - isAstCommaToken, - isAstElementAccessChain, - isAstExclamationToken, - isAstIdentifier, - isAstNonNullChain, - isAstNotEmittedStatement, - isAstOmittedExpression, - isAstOuterExpression, - isAstParenthesizedExpression, - isAstPrivateIdentifier, - isAstPropertyAccessChain, - isAstQuestionToken, - isAstVariableDeclaration, + astIsBinaryExpression, + astIsCallChain, + astIsCommaListExpression, + astIsCommaToken, + astIsElementAccessChain, + astIsExclamationToken, + astIsIdentifier, + astIsNonNullChain, + astIsNotEmittedStatement, + astIsOmittedExpression, + astIsParenthesizedExpression, + astIsPrivateIdentifier, + astIsPropertyAccessChain, + astIsQuestionToken, + astIsVariableDeclaration, isParseTreeNode, KeywordSyntaxKind, KeywordTypeSyntaxKind, @@ -347,6 +346,11 @@ import { TokenSyntaxKind, TransformFlags, Type, + astIsOuterExpression, + astNodeIsSynthesized, + astSetComment, + astGetComment, + AstHasComment, } from "../_namespaces/ts.js"; /** @internal */ @@ -2006,8 +2010,8 @@ export function createAstNodeFactory(flags: NodeFactoryFlags, onFinishNode?: (no const node = AstNode.PropertyDeclaration(); node.data.modifiers = asNodeArray(modifiers); node.data.name = asName(name); - node.data.questionToken = questionOrExclamationToken && isAstQuestionToken(questionOrExclamationToken) ? questionOrExclamationToken : undefined; - node.data.exclamationToken = questionOrExclamationToken && isAstExclamationToken(questionOrExclamationToken) ? questionOrExclamationToken : undefined; + node.data.questionToken = questionOrExclamationToken && astIsQuestionToken(questionOrExclamationToken) ? questionOrExclamationToken : undefined; + node.data.exclamationToken = questionOrExclamationToken && astIsExclamationToken(questionOrExclamationToken) ? questionOrExclamationToken : undefined; node.data.type = type; node.data.initializer = asInitializer(initializer); return finish(node); @@ -2024,8 +2028,8 @@ export function createAstNodeFactory(flags: NodeFactoryFlags, onFinishNode?: (no ) { return !sameNodeArray(node.data.modifiers, modifiers) || node.data.name !== name - || node.data.questionToken !== (questionOrExclamationToken !== undefined && isAstQuestionToken(questionOrExclamationToken) ? questionOrExclamationToken : undefined) - || node.data.exclamationToken !== (questionOrExclamationToken !== undefined && isAstExclamationToken(questionOrExclamationToken) ? questionOrExclamationToken : undefined) + || node.data.questionToken !== (questionOrExclamationToken !== undefined && astIsQuestionToken(questionOrExclamationToken) ? questionOrExclamationToken : undefined) + || node.data.exclamationToken !== (questionOrExclamationToken !== undefined && astIsExclamationToken(questionOrExclamationToken) ? questionOrExclamationToken : undefined) || node.data.type !== type || node.data.initializer !== initializer ? update(createPropertyDeclaration(modifiers, name, questionOrExclamationToken, type, initializer), node) @@ -2856,7 +2860,7 @@ export function createAstNodeFactory(flags: NodeFactoryFlags, onFinishNode?: (no // we end up with `[1, 2, ,]` instead of `[1, 2, ]` otherwise the `OmittedExpression` will just end up being treated like // a trailing comma. const lastElement = elements && lastOrUndefined(arrayItems(elements)); - const elementsArray = createNodeArray(elements, lastElement && isAstOmittedExpression(lastElement) ? true : undefined); + const elementsArray = createNodeArray(elements, lastElement && astIsOmittedExpression(lastElement) ? true : undefined); node.data.elements = parenthesizerRules().parenthesizeExpressionsOfCommaDelimitedList(elementsArray); node.data.multiLine = multiLine; return finish(node); @@ -2902,8 +2906,8 @@ export function createAstNodeFactory(flags: NodeFactoryFlags, onFinishNode?: (no // @api function updatePropertyAccessExpression(node: AstPropertyAccessExpression, expression: AstExpression, name: AstIdentifier | AstPrivateIdentifier) { - if (isAstPropertyAccessChain(node)) { - return updatePropertyAccessChain(node, expression, node.data.questionDotToken, cast(name, isAstIdentifier)); + if (astIsPropertyAccessChain(node)) { + return updatePropertyAccessChain(node, expression, node.data.questionDotToken, cast(name, astIsIdentifier)); } return node.data.expression !== expression || node.data.name !== name @@ -2950,7 +2954,7 @@ export function createAstNodeFactory(flags: NodeFactoryFlags, onFinishNode?: (no // @api function updateElementAccessExpression(node: AstElementAccessExpression, expression: AstExpression, argumentExpression: AstExpression) { - if (isAstElementAccessChain(node)) { + if (astIsElementAccessChain(node)) { return updateElementAccessChain(node, expression, node.data.questionDotToken, argumentExpression); } return node.data.expression !== expression @@ -2990,7 +2994,7 @@ export function createAstNodeFactory(flags: NodeFactoryFlags, onFinishNode?: (no // @api function updateCallExpression(node: AstCallExpression, expression: AstExpression, typeArguments: AstNodeArrayLike | undefined, argumentsArray: AstNodeArrayLike) { - if (isAstCallChain(node)) { + if (astIsCallChain(node)) { return updateCallChain(node, expression, node.data.questionDotToken, typeArguments, argumentsArray); } return node.data.expression !== expression @@ -3528,7 +3532,7 @@ export function createAstNodeFactory(flags: NodeFactoryFlags, onFinishNode?: (no // @api function updateNonNullExpression(node: AstNonNullExpression, expression: AstExpression) { - if (isAstNonNullChain(node)) { + if (astIsNonNullChain(node)) { return updateNonNullChain(node, expression); } return node.data.expression !== expression @@ -4695,7 +4699,7 @@ export function createAstNodeFactory(flags: NodeFactoryFlags, onFinishNode?: (no function createJSDocTemplateTag(tagName: AstIdentifier | undefined, constraint: AstJSDocTypeExpression | undefined, typeParameters: AstNodeArrayLike, comment?: string | AstNodeArray): AstJSDocTemplateTag { const node = AstNode.JSDocTemplateTag(); node.data.tagName = tagName ?? createIdentifier("template"); - node.data.comment = comment; + astSetComment(node, comment); node.data.constraint = constraint; node.data.typeParameters = createNodeArray(typeParameters); return finish(node); @@ -4706,7 +4710,7 @@ export function createAstNodeFactory(flags: NodeFactoryFlags, onFinishNode?: (no return node.data.tagName !== tagName || node.data.constraint !== constraint || !sameNodeArray(node.data.typeParameters, typeParameters) - || node.data.comment !== comment + || astGetComment(node) !== comment ? update(createJSDocTemplateTag(tagName, constraint, typeParameters, comment), node) : node; } @@ -4715,7 +4719,7 @@ export function createAstNodeFactory(flags: NodeFactoryFlags, onFinishNode?: (no function createJSDocTypedefTag(tagName: AstIdentifier | undefined, typeExpression?: AstJSDocTypeExpression, fullName?: AstIdentifier | AstJSDocNamespaceDeclaration, comment?: string | AstNodeArray): AstJSDocTypedefTag { const node = AstNode.JSDocTypedefTag(); node.data.tagName = tagName ?? createIdentifier("typedef"); - node.data.comment = comment; + astSetComment(node, comment); node.data.typeExpression = typeExpression; node.data.fullName = fullName; node.data.name = getJSDocTypeAliasName(fullName); @@ -4727,7 +4731,7 @@ export function createAstNodeFactory(flags: NodeFactoryFlags, onFinishNode?: (no return node.data.tagName !== tagName || node.data.typeExpression !== typeExpression || node.data.fullName !== fullName - || node.data.comment !== comment + || astGetComment(node) !== comment ? update(createJSDocTypedefTag(tagName, typeExpression, fullName, comment), node) : node; } @@ -4736,7 +4740,7 @@ export function createAstNodeFactory(flags: NodeFactoryFlags, onFinishNode?: (no function createJSDocParameterTag(tagName: AstIdentifier | undefined, name: AstEntityName, isBracketed: boolean, typeExpression?: AstJSDocTypeExpression, isNameFirst?: boolean, comment?: string | AstNodeArray): AstJSDocParameterTag { const node = AstNode.JSDocParameterTag(); node.data.tagName = tagName ?? createIdentifier("param"); - node.data.comment = comment; + astSetComment(node, comment); node.data.typeExpression = typeExpression; node.data.name = name; node.data.isNameFirst = !!isNameFirst; @@ -4751,7 +4755,7 @@ export function createAstNodeFactory(flags: NodeFactoryFlags, onFinishNode?: (no || node.data.isBracketed !== isBracketed || node.data.typeExpression !== typeExpression || node.data.isNameFirst !== isNameFirst - || node.data.comment !== comment + || astGetComment(node) !== comment ? update(createJSDocParameterTag(tagName, name, isBracketed, typeExpression, isNameFirst, comment), node) : node; } @@ -4760,7 +4764,7 @@ export function createAstNodeFactory(flags: NodeFactoryFlags, onFinishNode?: (no function createJSDocPropertyTag(tagName: AstIdentifier | undefined, name: AstEntityName, isBracketed: boolean, typeExpression?: AstJSDocTypeExpression, isNameFirst?: boolean, comment?: string | AstNodeArray): AstJSDocPropertyTag { const node = AstNode.JSDocPropertyTag(); node.data.tagName = tagName ?? createIdentifier("prop"); - node.data.comment = comment; + astSetComment(node, comment); node.data.typeExpression = typeExpression; node.data.name = name; node.data.isNameFirst = !!isNameFirst; @@ -4775,7 +4779,7 @@ export function createAstNodeFactory(flags: NodeFactoryFlags, onFinishNode?: (no || node.data.isBracketed !== isBracketed || node.data.typeExpression !== typeExpression || node.data.isNameFirst !== isNameFirst - || node.data.comment !== comment + || astGetComment(node) !== comment ? update(createJSDocPropertyTag(tagName, name, isBracketed, typeExpression, isNameFirst, comment), node) : node; } @@ -4784,7 +4788,7 @@ export function createAstNodeFactory(flags: NodeFactoryFlags, onFinishNode?: (no function createJSDocCallbackTag(tagName: AstIdentifier | undefined, typeExpression: AstJSDocSignature, fullName?: AstIdentifier | AstJSDocNamespaceDeclaration, comment?: string | AstNodeArray): AstJSDocCallbackTag { const node = AstNode.JSDocCallbackTag(); node.data.tagName = tagName ?? createIdentifier("callback"); - node.data.comment = comment; + astSetComment(node, comment); node.data.typeExpression = typeExpression; node.data.fullName = fullName; node.data.name = getJSDocTypeAliasName(fullName); @@ -4799,7 +4803,7 @@ export function createAstNodeFactory(flags: NodeFactoryFlags, onFinishNode?: (no return node.data.tagName !== tagName || node.data.typeExpression !== typeExpression || node.data.fullName !== fullName - || node.data.comment !== comment + || astGetComment(node) !== comment ? update(createJSDocCallbackTag(tagName, typeExpression, fullName, comment), node) : node; } @@ -4808,7 +4812,7 @@ export function createAstNodeFactory(flags: NodeFactoryFlags, onFinishNode?: (no function createJSDocOverloadTag(tagName: AstIdentifier | undefined, typeExpression: AstJSDocSignature, comment?: string | AstNodeArray): AstJSDocOverloadTag { const node = AstNode.JSDocOverloadTag(); node.data.tagName = tagName ?? createIdentifier("overload"); - node.data.comment = comment; + astSetComment(node, comment); node.data.typeExpression = typeExpression; return finish(node); } @@ -4817,7 +4821,7 @@ export function createAstNodeFactory(flags: NodeFactoryFlags, onFinishNode?: (no function updateJSDocOverloadTag(node: AstJSDocOverloadTag, tagName: AstIdentifier = getDefaultTagName(node), typeExpression: AstJSDocSignature, comment: string | AstNodeArray | undefined): AstJSDocOverloadTag { return node.data.tagName !== tagName || node.data.typeExpression !== typeExpression - || node.data.comment !== comment + || astGetComment(node) !== comment ? update(createJSDocOverloadTag(tagName, typeExpression, comment), node) : node; } @@ -4826,7 +4830,7 @@ export function createAstNodeFactory(flags: NodeFactoryFlags, onFinishNode?: (no function createJSDocAugmentsTag(tagName: AstIdentifier | undefined, className: AstJSDocAugmentsTag["data"]["class"], comment?: string | AstNodeArray): AstJSDocAugmentsTag { const node = AstNode.JSDocAugmentsTag(); node.data.tagName = tagName ?? createIdentifier("augments"); - node.data.comment = comment; + astSetComment(node, comment); node.data.class = className; return finish(node); } @@ -4835,7 +4839,7 @@ export function createAstNodeFactory(flags: NodeFactoryFlags, onFinishNode?: (no function updateJSDocAugmentsTag(node: AstJSDocAugmentsTag, tagName: AstIdentifier = getDefaultTagName(node), className: AstJSDocAugmentsTag["data"]["class"], comment: string | AstNodeArray | undefined): AstJSDocAugmentsTag { return node.data.tagName !== tagName || node.data.class !== className - || node.data.comment !== comment + || astGetComment(node) !== comment ? update(createJSDocAugmentsTag(tagName, className, comment), node) : node; } @@ -4844,7 +4848,7 @@ export function createAstNodeFactory(flags: NodeFactoryFlags, onFinishNode?: (no function createJSDocImplementsTag(tagName: AstIdentifier | undefined, className: AstJSDocImplementsTag["data"]["class"], comment?: string | AstNodeArray): AstJSDocImplementsTag { const node = AstNode.JSDocImplementsTag(); node.data.tagName = tagName ?? createIdentifier("implements"); - node.data.comment = comment; + astSetComment(node, comment); node.data.class = className; return finish(node); } @@ -4853,7 +4857,7 @@ export function createAstNodeFactory(flags: NodeFactoryFlags, onFinishNode?: (no function createJSDocSeeTag(tagName: AstIdentifier | undefined, name: AstJSDocNameReference | undefined, comment?: string | AstNodeArray): AstJSDocSeeTag { const node = AstNode.JSDocSeeTag(); node.data.tagName = tagName ?? createIdentifier("see"); - node.data.comment = comment; + astSetComment(node, comment); node.data.name = name; return finish(node); } @@ -4862,7 +4866,7 @@ export function createAstNodeFactory(flags: NodeFactoryFlags, onFinishNode?: (no function updateJSDocSeeTag(node: AstJSDocSeeTag, tagName: AstIdentifier | undefined, name: AstJSDocNameReference | undefined, comment?: string | AstNodeArray): AstJSDocSeeTag { return node.data.tagName !== tagName || node.data.name !== name - || node.data.comment !== comment + || astGetComment(node) !== comment ? update(createJSDocSeeTag(tagName, name, comment), node) : node; } @@ -4946,7 +4950,7 @@ export function createAstNodeFactory(flags: NodeFactoryFlags, onFinishNode?: (no function updateJSDocImplementsTag(node: AstJSDocImplementsTag, tagName: AstIdentifier = getDefaultTagName(node), className: AstJSDocImplementsTag["data"]["class"], comment: string | AstNodeArray | undefined): AstJSDocImplementsTag { return node.data.tagName !== tagName || node.data.class !== className - || node.data.comment !== comment + || astGetComment(node) !== comment ? update(createJSDocImplementsTag(tagName, className, comment), node) : node; } @@ -4962,7 +4966,7 @@ export function createAstNodeFactory(flags: NodeFactoryFlags, onFinishNode?: (no function createJSDocSimpleTag(makeTag: () => T, tagName: AstIdentifier | undefined, comment?: string | AstNodeArray) { const node = makeTag(); node.data.tagName = tagName ?? createIdentifier(getDefaultTagNameForKind(node.kind)); - node.data.comment = comment; + astSetComment(node as AstHasComment, comment); return finish(node); } @@ -4976,7 +4980,7 @@ export function createAstNodeFactory(flags: NodeFactoryFlags, onFinishNode?: (no // updateJSDocDeprecatedTag function updateJSDocSimpleTag(makeTag: () => T, node: T, tagName: AstIdentifier = getDefaultTagName(node), comment: string | AstNodeArray | undefined) { return node.data.tagName !== tagName - || node.data.comment !== comment + || astGetComment(node) !== comment ? update(createJSDocSimpleTag(makeTag, tagName, comment), node) : node; } @@ -5002,7 +5006,7 @@ export function createAstNodeFactory(flags: NodeFactoryFlags, onFinishNode?: (no function updateJSDocTypeLikeTag(makeTag: () => T, node: T, tagName: AstIdentifier = getDefaultTagName(node), typeExpression: AstJSDocTypeExpression | undefined, comment: string | AstNodeArray | undefined) { return node.data.tagName !== tagName || node.data.typeExpression !== typeExpression - || node.data.comment !== comment + || astGetComment(node) !== comment ? update(createJSDocTypeLikeTag(makeTag, tagName, typeExpression, comment), node) : node; } @@ -5016,7 +5020,7 @@ export function createAstNodeFactory(flags: NodeFactoryFlags, onFinishNode?: (no // @api function updateJSDocUnknownTag(node: AstJSDocUnknownTag, tagName: AstIdentifier, comment: string | AstNodeArray | undefined): AstJSDocUnknownTag { return node.data.tagName !== tagName - || node.data.comment !== comment + || astGetComment(node) !== comment ? update(createJSDocUnknownTag(tagName, comment), node) : node; } @@ -5032,7 +5036,7 @@ export function createAstNodeFactory(flags: NodeFactoryFlags, onFinishNode?: (no function updateJSDocEnumTag(node: AstJSDocEnumTag, tagName: AstIdentifier = getDefaultTagName(node), typeExpression: AstJSDocTypeExpression, comment: string | AstNodeArray | undefined) { return node.data.tagName !== tagName || node.data.typeExpression !== typeExpression - || node.data.comment !== comment + || astGetComment(node) !== comment ? update(createJSDocEnumTag(tagName, typeExpression, comment), node) : node; } @@ -5041,17 +5045,17 @@ export function createAstNodeFactory(flags: NodeFactoryFlags, onFinishNode?: (no function createJSDocImportTag(tagName: AstIdentifier | undefined, importClause: AstImportClause | undefined, moduleSpecifier: AstExpression, attributes?: AstImportAttributes, comment?: string | AstNodeArray): AstJSDocImportTag { const node = AstNode.JSDocImportTag(); node.data.tagName = tagName ?? createIdentifier("import"); - node.data.comment = comment; + astSetComment(node, comment); node.data.importClause = importClause; node.data.moduleSpecifier = moduleSpecifier; node.data.attributes = attributes; - node.data.comment = comment; + astSetComment(node, comment); return finish(node); } function updateJSDocImportTag(node: AstJSDocImportTag, tagName: AstIdentifier | undefined, importClause: AstImportClause | undefined, moduleSpecifier: AstExpression, attributes: AstImportAttributes | undefined, comment: string | AstNodeArray | undefined): AstJSDocImportTag { return node.data.tagName !== tagName - || node.data.comment !== comment + || astGetComment(node) !== comment || node.data.importClause !== importClause || node.data.moduleSpecifier !== moduleSpecifier || node.data.attributes !== attributes @@ -5076,14 +5080,14 @@ export function createAstNodeFactory(flags: NodeFactoryFlags, onFinishNode?: (no // @api function createJSDocComment(comment?: string | AstNodeArray | undefined, tags?: AstNodeArrayLike | undefined) { const node = AstNode.JSDocNode(); - node.data.comment = comment; + astSetComment(node, comment); node.data.tags = asNodeArray(tags); return finish(node); } // @api function updateJSDocComment(node: AstJSDoc, comment: string | AstNodeArray | undefined, tags: AstNodeArrayLike | undefined) { - return node.data.comment !== comment + return astGetComment(node) !== comment || !sameNodeArray(node.data.tags, tags) ? update(createJSDocComment(comment, tags), node) : node; @@ -5588,11 +5592,11 @@ export function createAstNodeFactory(flags: NodeFactoryFlags, onFinishNode?: (no } function flattenCommaElements(node: AstExpression): AstExpression | readonly AstExpression[] { - if (nodeIsSynthesized(node) && !isParseTreeNode(node) && !node.original && !node.emitNode && !node.id) { - if (isAstCommaListExpression(node)) { + if (astNodeIsSynthesized(node) && !isParseTreeNode(node) && !node.original && !node.emitNode && !node.id) { + if (astIsCommaListExpression(node)) { return node.data.elements.items; } - if (isAstBinaryExpression(node) && isAstCommaToken(node.data.operatorToken)) { + if (astIsBinaryExpression(node) && astIsCommaToken(node.data.operatorToken)) { return [node.data.left, node.data.right]; } } @@ -5645,8 +5649,8 @@ export function createAstNodeFactory(flags: NodeFactoryFlags, onFinishNode?: (no clone.emitNode = undefined; setOriginal(clone, node); - if (isAstIdentifier(node)) { - Debug.assert(isAstIdentifier(clone)); + if (astIsIdentifier(node)) { + Debug.assert(astIsIdentifier(clone)); const typeArguments = getIdentifierTypeArguments(node); if (typeArguments) setIdentifierTypeArguments(clone, typeArguments); @@ -5654,8 +5658,8 @@ export function createAstNodeFactory(flags: NodeFactoryFlags, onFinishNode?: (no const autoGenerate = getIdentifierAutoGenerate(node); if (autoGenerate) setIdentifierAutoGenerate(clone, { ...autoGenerate }); } - else if (isAstPrivateIdentifier(node)) { - Debug.assert(isAstPrivateIdentifier(clone)); + else if (astIsPrivateIdentifier(node)) { + Debug.assert(astIsPrivateIdentifier(clone)); const autoGenerate = getIdentifierAutoGenerate(node); if (autoGenerate) setIdentifierAutoGenerate(clone, { ...autoGenerate }); @@ -5702,8 +5706,8 @@ export function createAstNodeFactory(flags: NodeFactoryFlags, onFinishNode?: (no * the containing expression is created/updated. */ function isIgnorableParen(node: AstExpression) { - return isAstParenthesizedExpression(node) - && nodeIsSynthesized(node) + return astIsParenthesizedExpression(node) + && astNodeIsSynthesized(node) && nodeIsSynthesized(getSourceMapRange(node)) && nodeIsSynthesized(getCommentRange(node)) && !some(getSyntheticLeadingComments(node)) @@ -5711,7 +5715,7 @@ export function createAstNodeFactory(flags: NodeFactoryFlags, onFinishNode?: (no } function restoreOuterExpressions(outerExpression: AstExpression | undefined, innerExpression: AstExpression, kinds = OuterExpressionKinds.All): AstExpression { - if (outerExpression && isAstOuterExpression(outerExpression, kinds) && !isIgnorableParen(outerExpression)) { + if (outerExpression && astIsOuterExpression(outerExpression, kinds) && !isIgnorableParen(outerExpression)) { return updateOuterExpression( outerExpression, restoreOuterExpressions(outerExpression.data.expression, innerExpression), @@ -5749,11 +5753,11 @@ export function createAstNodeFactory(flags: NodeFactoryFlags, onFinishNode?: (no function asEmbeddedStatement(statement: T): T | AstEmptyStatement; function asEmbeddedStatement(statement: T | undefined): T | AstEmptyStatement | undefined; function asEmbeddedStatement(statement: T | undefined): T | AstEmptyStatement | undefined { - return statement && isAstNotEmittedStatement(statement) ? setTextRange(setOriginal(createEmptyStatement(), statement), statement) : statement; + return statement && astIsNotEmittedStatement(statement) ? setTextRange(setOriginal(createEmptyStatement(), statement), statement) : statement; } function asVariableDeclaration(variableDeclaration: string | AstBindingName | AstVariableDeclaration | undefined) { - if (typeof variableDeclaration === "string" || variableDeclaration && !isAstVariableDeclaration(variableDeclaration)) { + if (typeof variableDeclaration === "string" || variableDeclaration && !astIsVariableDeclaration(variableDeclaration)) { return createVariableDeclaration( variableDeclaration, /*exclamationToken*/ undefined, @@ -5911,8 +5915,8 @@ function getJSDocTypeAliasName(fullName: AstJSDocNamespaceBody | undefined) { if (fullName) { let rightNode = fullName; while (true) { - if (isAstIdentifier(rightNode) || !rightNode.data.body) { - return isAstIdentifier(rightNode) ? rightNode : rightNode.data.name; + if (astIsIdentifier(rightNode) || !rightNode.data.body) { + return astIsIdentifier(rightNode) ? rightNode : rightNode.data.name; } rightNode = rightNode.data.body; } diff --git a/src/compiler/factory/astNodeTests.ts b/src/compiler/factory/astNodeTests.ts index 6a891f0b8b4..a67fa7d9f75 100644 --- a/src/compiler/factory/astNodeTests.ts +++ b/src/compiler/factory/astNodeTests.ts @@ -13,9 +13,8 @@ import { AstDeclareKeyword, AstElementAccessChain, AsteriskToken, - AstHasDecorators, + AstExpression, AstHasJSDoc, - AstHasModifiers, AstLeftHandSideExpression, AstNode, AstNonNullChain, @@ -96,6 +95,7 @@ import { InferTypeNode, InterfaceDeclaration, IntersectionTypeNode, + isExpressionKind, isLeftHandSideExpressionKind, JSDoc, JSDocAllType, @@ -205,7 +205,7 @@ import { SemicolonClassElement, SetAccessorDeclaration, ShorthandPropertyAssignment, - skipAstOuterExpressions, + astSkipOuterExpressions, SourceFile, SpreadAssignment, SpreadElement, @@ -252,757 +252,757 @@ import { // Literals /** @internal */ -export function isAstNumericLiteral(node: AstNode): node is AstNode { +export function astIsNumericLiteral(node: AstNode): node is AstNode { return node.kind === SyntaxKind.NumericLiteral; } /** @internal */ -export function isAstBigIntLiteral(node: AstNode): node is AstNode { +export function astIsBigIntLiteral(node: AstNode): node is AstNode { return node.kind === SyntaxKind.BigIntLiteral; } /** @internal */ -export function isAstStringLiteral(node: AstNode): node is AstNode { +export function astIsStringLiteral(node: AstNode): node is AstNode { return node.kind === SyntaxKind.StringLiteral; } /** @internal */ -export function isAstJsxText(node: AstNode): node is AstNode { +export function astIsJsxText(node: AstNode): node is AstNode { return node.kind === SyntaxKind.JsxText; } /** @internal */ -export function isAstRegularExpressionLiteral(node: AstNode): node is AstNode { +export function astIsRegularExpressionLiteral(node: AstNode): node is AstNode { return node.kind === SyntaxKind.RegularExpressionLiteral; } /** @internal */ -export function isAstNoSubstitutionTemplateLiteral(node: AstNode): node is AstNode { +export function astIsNoSubstitutionTemplateLiteral(node: AstNode): node is AstNode { return node.kind === SyntaxKind.NoSubstitutionTemplateLiteral; } // Pseudo-literals /** @internal */ -export function isAstTemplateHead(node: AstNode): node is AstNode { +export function astIsTemplateHead(node: AstNode): node is AstNode { return node.kind === SyntaxKind.TemplateHead; } /** @internal */ -export function isAstTemplateMiddle(node: AstNode): node is AstNode { +export function astIsTemplateMiddle(node: AstNode): node is AstNode { return node.kind === SyntaxKind.TemplateMiddle; } /** @internal */ -export function isAstTemplateTail(node: AstNode): node is AstNode { +export function astIsTemplateTail(node: AstNode): node is AstNode { return node.kind === SyntaxKind.TemplateTail; } // Punctuation /** @internal */ -export function isAstDotDotDotToken(node: AstNode): node is AstNode { +export function astIsDotDotDotToken(node: AstNode): node is AstNode { return node.kind === SyntaxKind.DotDotDotToken; } /** @internal */ -export function isAstCommaToken(node: AstNode): node is AstNode> { +export function astIsCommaToken(node: AstNode): node is AstNode> { return node.kind === SyntaxKind.CommaToken; } /** @internal */ -export function isAstPlusToken(node: AstNode): node is AstNode { +export function astIsPlusToken(node: AstNode): node is AstNode { return node.kind === SyntaxKind.PlusToken; } /** @internal */ -export function isAstMinusToken(node: AstNode): node is AstNode { +export function astIsMinusToken(node: AstNode): node is AstNode { return node.kind === SyntaxKind.MinusToken; } /** @internal */ -export function isAstAsteriskToken(node: AstNode): node is AstNode { +export function astIsAsteriskToken(node: AstNode): node is AstNode { return node.kind === SyntaxKind.AsteriskToken; } /** @internal */ -export function isAstExclamationToken(node: AstNode): node is AstNode { +export function astIsExclamationToken(node: AstNode): node is AstNode { return node.kind === SyntaxKind.ExclamationToken; } /** @internal */ -export function isAstQuestionToken(node: AstNode): node is AstNode { +export function astIsQuestionToken(node: AstNode): node is AstNode { return node.kind === SyntaxKind.QuestionToken; } /** @internal */ -export function isAstColonToken(node: AstNode): node is AstNode { +export function astIsColonToken(node: AstNode): node is AstNode { return node.kind === SyntaxKind.ColonToken; } /** @internal */ -export function isAstQuestionDotToken(node: AstNode): node is AstNode { +export function astIsQuestionDotToken(node: AstNode): node is AstNode { return node.kind === SyntaxKind.QuestionDotToken; } /** @internal */ -export function isAstEqualsGreaterThanToken(node: AstNode): node is AstNode { +export function astIsEqualsGreaterThanToken(node: AstNode): node is AstNode { return node.kind === SyntaxKind.EqualsGreaterThanToken; } // Identifiers /** @internal */ -export function isAstIdentifier(node: AstNode): node is AstNode { +export function astIsIdentifier(node: AstNode): node is AstNode { return node.kind === SyntaxKind.Identifier; } /** @internal */ -export function isAstPrivateIdentifier(node: AstNode): node is AstNode { +export function astIsPrivateIdentifier(node: AstNode): node is AstNode { return node.kind === SyntaxKind.PrivateIdentifier; } // Reserved Words /** @internal */ -export function isAstExportModifier(node: AstNode): node is AstNode { +export function astIsExportModifier(node: AstNode): node is AstNode { return node.kind === SyntaxKind.ExportKeyword; } /** @internal */ -export function isAstDefaultModifier(node: AstNode): node is AstNode { +export function astIsDefaultModifier(node: AstNode): node is AstNode { return node.kind === SyntaxKind.DefaultKeyword; } /** @internal */ -export function isAstAsyncModifier(node: AstNode): node is AstNode { +export function astIsAsyncModifier(node: AstNode): node is AstNode { return node.kind === SyntaxKind.AsyncKeyword; } /** @internal */ -export function isAstAssertsKeyword(node: AstNode): node is AstNode { +export function astIsAssertsKeyword(node: AstNode): node is AstNode { return node.kind === SyntaxKind.AssertsKeyword; } /** @internal */ -export function isAstAwaitKeyword(node: AstNode): node is AstNode { +export function astIsAwaitKeyword(node: AstNode): node is AstNode { return node.kind === SyntaxKind.AwaitKeyword; } /** @internal */ -export function isAstReadonlyKeyword(node: AstNode): node is AstNode { +export function astIsReadonlyKeyword(node: AstNode): node is AstNode { return node.kind === SyntaxKind.ReadonlyKeyword; } /** @internal */ -export function isAstStaticModifier(node: AstNode): node is AstNode { +export function astIsStaticModifier(node: AstNode): node is AstNode { return node.kind === SyntaxKind.StaticKeyword; } /** @internal */ -export function isAstAbstractModifier(node: AstNode): node is AstNode { +export function astIsAbstractModifier(node: AstNode): node is AstNode { return node.kind === SyntaxKind.AbstractKeyword; } /** @internal */ -export function isAstOverrideModifier(node: AstNode): node is AstNode { +export function astIsOverrideModifier(node: AstNode): node is AstNode { return node.kind === SyntaxKind.OverrideKeyword; } /** @internal */ -export function isAstAccessorModifier(node: AstNode): node is AstNode { +export function astIsAccessorModifier(node: AstNode): node is AstNode { return node.kind === SyntaxKind.AccessorKeyword; } /** @internal */ -export function isAstSuperKeyword(node: AstNode): node is AstNode { +export function astIsSuperKeyword(node: AstNode): node is AstNode { return node.kind === SyntaxKind.SuperKeyword; } /** @internal */ -export function isAstImportKeyword(node: AstNode): node is AstNode { +export function astIsImportKeyword(node: AstNode): node is AstNode { return node.kind === SyntaxKind.ImportKeyword; } /** @internal */ -export function isAstCaseKeyword(node: AstNode): node is AstNode { +export function astIsCaseKeyword(node: AstNode): node is AstNode { return node.kind === SyntaxKind.CaseKeyword; } /** @internal */ -export function isAstDeclareKeyword(node: AstNode): node is AstDeclareKeyword { +export function astIsDeclareKeyword(node: AstNode): node is AstDeclareKeyword { return node.kind === SyntaxKind.DeclareKeyword; } // Names /** @internal */ -export function isAstQualifiedName(node: AstNode): node is AstNode { +export function astIsQualifiedName(node: AstNode): node is AstNode { return node.kind === SyntaxKind.QualifiedName; } /** @internal */ -export function isAstComputedPropertyName(node: AstNode): node is AstNode { +export function astIsComputedPropertyName(node: AstNode): node is AstNode { return node.kind === SyntaxKind.ComputedPropertyName; } // Signature elements /** @internal */ -export function isAstTypeParameterDeclaration(node: AstNode): node is AstNode { +export function astIsTypeParameterDeclaration(node: AstNode): node is AstNode { return node.kind === SyntaxKind.TypeParameter; } /** @internal */ // TODO(rbuckton): Rename to 'isParameterDeclaration' -export function isAstParameter(node: AstNode): node is AstNode { +export function astIsParameter(node: AstNode): node is AstNode { return node.kind === SyntaxKind.Parameter; } /** @internal */ -export function isAstDecorator(node: AstNode): node is AstNode { +export function astIsDecorator(node: AstNode): node is AstNode { return node.kind === SyntaxKind.Decorator; } // TypeMember /** @internal */ -export function isAstPropertySignature(node: AstNode): node is AstNode { +export function astIsPropertySignature(node: AstNode): node is AstNode { return node.kind === SyntaxKind.PropertySignature; } /** @internal */ -export function isAstPropertyDeclaration(node: AstNode): node is AstNode { +export function astIsPropertyDeclaration(node: AstNode): node is AstNode { return node.kind === SyntaxKind.PropertyDeclaration; } /** @internal */ -export function isAstMethodSignature(node: AstNode): node is AstNode { +export function astIsMethodSignature(node: AstNode): node is AstNode { return node.kind === SyntaxKind.MethodSignature; } /** @internal */ -export function isAstMethodDeclaration(node: AstNode): node is AstNode { +export function astIsMethodDeclaration(node: AstNode): node is AstNode { return node.kind === SyntaxKind.MethodDeclaration; } /** @internal */ -export function isAstClassStaticBlockDeclaration(node: AstNode): node is AstNode { +export function astIsClassStaticBlockDeclaration(node: AstNode): node is AstNode { return node.kind === SyntaxKind.ClassStaticBlockDeclaration; } /** @internal */ -export function isAstConstructorDeclaration(node: AstNode): node is AstNode { +export function astIsConstructorDeclaration(node: AstNode): node is AstNode { return node.kind === SyntaxKind.Constructor; } /** @internal */ -export function isAstGetAccessorDeclaration(node: AstNode): node is AstNode { +export function astIsGetAccessorDeclaration(node: AstNode): node is AstNode { return node.kind === SyntaxKind.GetAccessor; } /** @internal */ -export function isAstSetAccessorDeclaration(node: AstNode): node is AstNode { +export function astIsSetAccessorDeclaration(node: AstNode): node is AstNode { return node.kind === SyntaxKind.SetAccessor; } /** @internal */ -export function isAstCallSignatureDeclaration(node: AstNode): node is AstNode { +export function astIsCallSignatureDeclaration(node: AstNode): node is AstNode { return node.kind === SyntaxKind.CallSignature; } /** @internal */ -export function isAstConstructSignatureDeclaration(node: AstNode): node is AstNode { +export function astIsConstructSignatureDeclaration(node: AstNode): node is AstNode { return node.kind === SyntaxKind.ConstructSignature; } /** @internal */ -export function isAstIndexSignatureDeclaration(node: AstNode): node is AstNode { +export function astIsIndexSignatureDeclaration(node: AstNode): node is AstNode { return node.kind === SyntaxKind.IndexSignature; } // Type /** @internal */ -export function isAstTypePredicateNode(node: AstNode): node is AstNode { +export function astIsTypePredicateNode(node: AstNode): node is AstNode { return node.kind === SyntaxKind.TypePredicate; } /** @internal */ -export function isAstTypeReferenceNode(node: AstNode): node is AstNode { +export function astIsTypeReferenceNode(node: AstNode): node is AstNode { return node.kind === SyntaxKind.TypeReference; } /** @internal */ -export function isAstFunctionTypeNode(node: AstNode): node is AstNode { +export function astIsFunctionTypeNode(node: AstNode): node is AstNode { return node.kind === SyntaxKind.FunctionType; } /** @internal */ -export function isAstConstructorTypeNode(node: AstNode): node is AstNode { +export function astIsConstructorTypeNode(node: AstNode): node is AstNode { return node.kind === SyntaxKind.ConstructorType; } /** @internal */ -export function isAstTypeQueryNode(node: AstNode): node is AstNode { +export function astIsTypeQueryNode(node: AstNode): node is AstNode { return node.kind === SyntaxKind.TypeQuery; } /** @internal */ -export function isAstTypeLiteralNode(node: AstNode): node is AstNode { +export function astIsTypeLiteralNode(node: AstNode): node is AstNode { return node.kind === SyntaxKind.TypeLiteral; } /** @internal */ -export function isAstArrayTypeNode(node: AstNode): node is AstNode { +export function astIsArrayTypeNode(node: AstNode): node is AstNode { return node.kind === SyntaxKind.ArrayType; } /** @internal */ -export function isAstTupleTypeNode(node: AstNode): node is AstNode { +export function astIsTupleTypeNode(node: AstNode): node is AstNode { return node.kind === SyntaxKind.TupleType; } /** @internal */ -export function isAstNamedTupleMember(node: AstNode): node is AstNode { +export function astIsNamedTupleMember(node: AstNode): node is AstNode { return node.kind === SyntaxKind.NamedTupleMember; } /** @internal */ -export function isAstOptionalTypeNode(node: AstNode): node is AstNode { +export function astIsOptionalTypeNode(node: AstNode): node is AstNode { return node.kind === SyntaxKind.OptionalType; } /** @internal */ -export function isAstRestTypeNode(node: AstNode): node is AstNode { +export function astIsRestTypeNode(node: AstNode): node is AstNode { return node.kind === SyntaxKind.RestType; } /** @internal */ -export function isAstUnionTypeNode(node: AstNode): node is AstNode { +export function astIsUnionTypeNode(node: AstNode): node is AstNode { return node.kind === SyntaxKind.UnionType; } /** @internal */ -export function isAstIntersectionTypeNode(node: AstNode): node is AstNode { +export function astIsIntersectionTypeNode(node: AstNode): node is AstNode { return node.kind === SyntaxKind.IntersectionType; } /** @internal */ -export function isAstConditionalTypeNode(node: AstNode): node is AstNode { +export function astIsConditionalTypeNode(node: AstNode): node is AstNode { return node.kind === SyntaxKind.ConditionalType; } /** @internal */ -export function isAstInferTypeNode(node: AstNode): node is AstNode { +export function astIsInferTypeNode(node: AstNode): node is AstNode { return node.kind === SyntaxKind.InferType; } /** @internal */ -export function isAstParenthesizedTypeNode(node: AstNode): node is AstNode { +export function astIsParenthesizedTypeNode(node: AstNode): node is AstNode { return node.kind === SyntaxKind.ParenthesizedType; } /** @internal */ -export function isAstThisTypeNode(node: AstNode): node is AstNode { +export function astIsThisTypeNode(node: AstNode): node is AstNode { return node.kind === SyntaxKind.ThisType; } /** @internal */ -export function isAstTypeOperatorNode(node: AstNode): node is AstNode { +export function astIsTypeOperatorNode(node: AstNode): node is AstNode { return node.kind === SyntaxKind.TypeOperator; } /** @internal */ -export function isAstIndexedAccessTypeNode(node: AstNode): node is AstNode { +export function astIsIndexedAccessTypeNode(node: AstNode): node is AstNode { return node.kind === SyntaxKind.IndexedAccessType; } /** @internal */ -export function isAstMappedTypeNode(node: AstNode): node is AstNode { +export function astIsMappedTypeNode(node: AstNode): node is AstNode { return node.kind === SyntaxKind.MappedType; } /** @internal */ -export function isAstLiteralTypeNode(node: AstNode): node is AstNode { +export function astIsLiteralTypeNode(node: AstNode): node is AstNode { return node.kind === SyntaxKind.LiteralType; } /** @internal */ -export function isAstImportTypeNode(node: AstNode): node is AstNode { +export function astIsImportTypeNode(node: AstNode): node is AstNode { return node.kind === SyntaxKind.ImportType; } /** @internal */ -export function isAstTemplateLiteralTypeSpan(node: AstNode): node is AstNode { +export function astIsTemplateLiteralTypeSpan(node: AstNode): node is AstNode { return node.kind === SyntaxKind.TemplateLiteralTypeSpan; } /** @internal */ -export function isAstTemplateLiteralTypeNode(node: AstNode): node is AstNode { +export function astIsTemplateLiteralTypeNode(node: AstNode): node is AstNode { return node.kind === SyntaxKind.TemplateLiteralType; } // Binding patterns /** @internal */ -export function isAstObjectBindingPattern(node: AstNode): node is AstNode { +export function astIsObjectBindingPattern(node: AstNode): node is AstNode { return node.kind === SyntaxKind.ObjectBindingPattern; } /** @internal */ -export function isAstArrayBindingPattern(node: AstNode): node is AstNode { +export function astIsArrayBindingPattern(node: AstNode): node is AstNode { return node.kind === SyntaxKind.ArrayBindingPattern; } /** @internal */ -export function isAstBindingElement(node: AstNode): node is AstNode { +export function astIsBindingElement(node: AstNode): node is AstNode { return node.kind === SyntaxKind.BindingElement; } // Expression /** @internal */ -export function isAstArrayLiteralExpression(node: AstNode): node is AstNode { +export function astIsArrayLiteralExpression(node: AstNode): node is AstNode { return node.kind === SyntaxKind.ArrayLiteralExpression; } /** @internal */ -export function isAstObjectLiteralExpression(node: AstNode): node is AstNode { +export function astIsObjectLiteralExpression(node: AstNode): node is AstNode { return node.kind === SyntaxKind.ObjectLiteralExpression; } /** @internal */ -export function isAstPropertyAccessExpression(node: AstNode): node is AstNode { +export function astIsPropertyAccessExpression(node: AstNode): node is AstNode { return node.kind === SyntaxKind.PropertyAccessExpression; } /** @internal */ -export function isAstElementAccessExpression(node: AstNode): node is AstNode { +export function astIsElementAccessExpression(node: AstNode): node is AstNode { return node.kind === SyntaxKind.ElementAccessExpression; } /** @internal */ -export function isAstCallExpression(node: AstNode): node is AstNode { +export function astIsCallExpression(node: AstNode): node is AstNode { return node.kind === SyntaxKind.CallExpression; } /** @internal */ -export function isAstNewExpression(node: AstNode): node is AstNode { +export function astIsNewExpression(node: AstNode): node is AstNode { return node.kind === SyntaxKind.NewExpression; } /** @internal */ -export function isAstTaggedTemplateExpression(node: AstNode): node is AstNode { +export function astIsTaggedTemplateExpression(node: AstNode): node is AstNode { return node.kind === SyntaxKind.TaggedTemplateExpression; } /** @internal */ -export function isAstTypeAssertionExpression(node: AstNode): node is AstNode { +export function astIsTypeAssertionExpression(node: AstNode): node is AstNode { return node.kind === SyntaxKind.TypeAssertionExpression; } /** @internal */ -export function isAstParenthesizedExpression(node: AstNode): node is AstNode { +export function astIsParenthesizedExpression(node: AstNode): node is AstNode { return node.kind === SyntaxKind.ParenthesizedExpression; } /** @internal */ -export function isAstFunctionExpression(node: AstNode): node is AstNode { +export function astIsFunctionExpression(node: AstNode): node is AstNode { return node.kind === SyntaxKind.FunctionExpression; } /** @internal */ -export function isAstArrowFunction(node: AstNode): node is AstNode { +export function astIsArrowFunction(node: AstNode): node is AstNode { return node.kind === SyntaxKind.ArrowFunction; } /** @internal */ -export function isAstDeleteExpression(node: AstNode): node is AstNode { +export function astIsDeleteExpression(node: AstNode): node is AstNode { return node.kind === SyntaxKind.DeleteExpression; } /** @internal */ -export function isAstTypeOfExpression(node: AstNode): node is AstNode { +export function astIsTypeOfExpression(node: AstNode): node is AstNode { return node.kind === SyntaxKind.TypeOfExpression; } /** @internal */ -export function isAstVoidExpression(node: AstNode): node is AstNode { +export function astIsVoidExpression(node: AstNode): node is AstNode { return node.kind === SyntaxKind.VoidExpression; } /** @internal */ -export function isAstAwaitExpression(node: AstNode): node is AstNode { +export function astIsAwaitExpression(node: AstNode): node is AstNode { return node.kind === SyntaxKind.AwaitExpression; } /** @internal */ -export function isAstPrefixUnaryExpression(node: AstNode): node is AstNode { +export function astIsPrefixUnaryExpression(node: AstNode): node is AstNode { return node.kind === SyntaxKind.PrefixUnaryExpression; } /** @internal */ -export function isAstPostfixUnaryExpression(node: AstNode): node is AstNode { +export function astIsPostfixUnaryExpression(node: AstNode): node is AstNode { return node.kind === SyntaxKind.PostfixUnaryExpression; } /** @internal */ -export function isAstBinaryExpression(node: AstNode): node is AstNode { +export function astIsBinaryExpression(node: AstNode): node is AstNode { return node.kind === SyntaxKind.BinaryExpression; } /** @internal */ -export function isAstConditionalExpression(node: AstNode): node is AstNode { +export function astIsConditionalExpression(node: AstNode): node is AstNode { return node.kind === SyntaxKind.ConditionalExpression; } /** @internal */ -export function isAstTemplateExpression(node: AstNode): node is AstNode { +export function astIsTemplateExpression(node: AstNode): node is AstNode { return node.kind === SyntaxKind.TemplateExpression; } /** @internal */ -export function isAstYieldExpression(node: AstNode): node is AstNode { +export function astIsYieldExpression(node: AstNode): node is AstNode { return node.kind === SyntaxKind.YieldExpression; } /** @internal */ -export function isAstSpreadElement(node: AstNode): node is AstNode { +export function astIsSpreadElement(node: AstNode): node is AstNode { return node.kind === SyntaxKind.SpreadElement; } /** @internal */ -export function isAstClassExpression(node: AstNode): node is AstNode { +export function astIsClassExpression(node: AstNode): node is AstNode { return node.kind === SyntaxKind.ClassExpression; } /** @internal */ -export function isAstOmittedExpression(node: AstNode): node is AstNode { +export function astIsOmittedExpression(node: AstNode): node is AstNode { return node.kind === SyntaxKind.OmittedExpression; } /** @internal */ -export function isAstExpressionWithTypeArguments(node: AstNode): node is AstNode { +export function astIsExpressionWithTypeArguments(node: AstNode): node is AstNode { return node.kind === SyntaxKind.ExpressionWithTypeArguments; } /** @internal */ -export function isAstAsExpression(node: AstNode): node is AstNode { +export function astIsAsExpression(node: AstNode): node is AstNode { return node.kind === SyntaxKind.AsExpression; } /** @internal */ -export function isAstSatisfiesExpression(node: AstNode): node is AstNode { +export function astIsSatisfiesExpression(node: AstNode): node is AstNode { return node.kind === SyntaxKind.SatisfiesExpression; } /** @internal */ -export function isAstNonNullExpression(node: AstNode): node is AstNode { +export function astIsNonNullExpression(node: AstNode): node is AstNode { return node.kind === SyntaxKind.NonNullExpression; } /** @internal */ -export function isAstMetaProperty(node: AstNode): node is AstNode { +export function astIsMetaProperty(node: AstNode): node is AstNode { return node.kind === SyntaxKind.MetaProperty; } /** @internal */ -export function isAstSyntheticExpression(node: AstNode): node is AstNode { +export function astIsSyntheticExpression(node: AstNode): node is AstNode { return node.kind === SyntaxKind.SyntheticExpression; } /** @internal */ -export function isAstPartiallyEmittedExpression(node: AstNode): node is AstNode { +export function astIsPartiallyEmittedExpression(node: AstNode): node is AstNode { return node.kind === SyntaxKind.PartiallyEmittedExpression; } /** @internal */ -export function isAstCommaListExpression(node: AstNode): node is AstNode { +export function astIsCommaListExpression(node: AstNode): node is AstNode { return node.kind === SyntaxKind.CommaListExpression; } // Misc /** @internal */ -export function isAstTemplateSpan(node: AstNode): node is AstNode { +export function astIsTemplateSpan(node: AstNode): node is AstNode { return node.kind === SyntaxKind.TemplateSpan; } /** @internal */ -export function isAstSemicolonClassElement(node: AstNode): node is AstNode { +export function astIsSemicolonClassElement(node: AstNode): node is AstNode { return node.kind === SyntaxKind.SemicolonClassElement; } // Elements /** @internal */ -export function isAstBlock(node: AstNode): node is AstNode { +export function astIsBlock(node: AstNode): node is AstNode { return node.kind === SyntaxKind.Block; } /** @internal */ -export function isAstVariableStatement(node: AstNode): node is AstNode { +export function astIsVariableStatement(node: AstNode): node is AstNode { return node.kind === SyntaxKind.VariableStatement; } /** @internal */ -export function isAstEmptyStatement(node: AstNode): node is AstNode { +export function astIsEmptyStatement(node: AstNode): node is AstNode { return node.kind === SyntaxKind.EmptyStatement; } /** @internal */ -export function isAstExpressionStatement(node: AstNode): node is AstNode { +export function astIsExpressionStatement(node: AstNode): node is AstNode { return node.kind === SyntaxKind.ExpressionStatement; } /** @internal */ -export function isAstIfStatement(node: AstNode): node is AstNode { +export function astIsIfStatement(node: AstNode): node is AstNode { return node.kind === SyntaxKind.IfStatement; } /** @internal */ -export function isAstDoStatement(node: AstNode): node is AstNode { +export function astIsDoStatement(node: AstNode): node is AstNode { return node.kind === SyntaxKind.DoStatement; } /** @internal */ -export function isAstWhileStatement(node: AstNode): node is AstNode { +export function astIsWhileStatement(node: AstNode): node is AstNode { return node.kind === SyntaxKind.WhileStatement; } /** @internal */ -export function isAstForStatement(node: AstNode): node is AstNode { +export function astIsForStatement(node: AstNode): node is AstNode { return node.kind === SyntaxKind.ForStatement; } /** @internal */ -export function isAstForInStatement(node: AstNode): node is AstNode { +export function astIsForInStatement(node: AstNode): node is AstNode { return node.kind === SyntaxKind.ForInStatement; } /** @internal */ -export function isAstForOfStatement(node: AstNode): node is AstNode { +export function astIsForOfStatement(node: AstNode): node is AstNode { return node.kind === SyntaxKind.ForOfStatement; } /** @internal */ -export function isAstContinueStatement(node: AstNode): node is AstNode { +export function astIsContinueStatement(node: AstNode): node is AstNode { return node.kind === SyntaxKind.ContinueStatement; } /** @internal */ -export function isAstBreakStatement(node: AstNode): node is AstNode { +export function astIsBreakStatement(node: AstNode): node is AstNode { return node.kind === SyntaxKind.BreakStatement; } /** @internal */ -export function isAstReturnStatement(node: AstNode): node is AstNode { +export function astIsReturnStatement(node: AstNode): node is AstNode { return node.kind === SyntaxKind.ReturnStatement; } /** @internal */ -export function isAstWithStatement(node: AstNode): node is AstNode { +export function astIsWithStatement(node: AstNode): node is AstNode { return node.kind === SyntaxKind.WithStatement; } /** @internal */ -export function isAstSwitchStatement(node: AstNode): node is AstNode { +export function astIsSwitchStatement(node: AstNode): node is AstNode { return node.kind === SyntaxKind.SwitchStatement; } /** @internal */ -export function isAstLabeledStatement(node: AstNode): node is AstNode { +export function astIsLabeledStatement(node: AstNode): node is AstNode { return node.kind === SyntaxKind.LabeledStatement; } /** @internal */ -export function isAstThrowStatement(node: AstNode): node is AstNode { +export function astIsThrowStatement(node: AstNode): node is AstNode { return node.kind === SyntaxKind.ThrowStatement; } /** @internal */ -export function isAstTryStatement(node: AstNode): node is AstNode { +export function astIsTryStatement(node: AstNode): node is AstNode { return node.kind === SyntaxKind.TryStatement; } /** @internal */ -export function isAstDebuggerStatement(node: AstNode): node is AstNode { +export function astIsDebuggerStatement(node: AstNode): node is AstNode { return node.kind === SyntaxKind.DebuggerStatement; } /** @internal */ -export function isAstVariableDeclaration(node: AstNode): node is AstNode { +export function astIsVariableDeclaration(node: AstNode): node is AstNode { return node.kind === SyntaxKind.VariableDeclaration; } /** @internal */ -export function isAstVariableDeclarationList(node: AstNode): node is AstNode { +export function astIsVariableDeclarationList(node: AstNode): node is AstNode { return node.kind === SyntaxKind.VariableDeclarationList; } /** @internal */ -export function isAstFunctionDeclaration(node: AstNode): node is AstNode { +export function astIsFunctionDeclaration(node: AstNode): node is AstNode { return node.kind === SyntaxKind.FunctionDeclaration; } /** @internal */ -export function isAstClassDeclaration(node: AstNode): node is AstNode { +export function astIsClassDeclaration(node: AstNode): node is AstNode { return node.kind === SyntaxKind.ClassDeclaration; } /** @internal */ -export function isAstInterfaceDeclaration(node: AstNode): node is AstNode { +export function astIsInterfaceDeclaration(node: AstNode): node is AstNode { return node.kind === SyntaxKind.InterfaceDeclaration; } /** @internal */ -export function isAstTypeAliasDeclaration(node: AstNode): node is AstNode { +export function astIsTypeAliasDeclaration(node: AstNode): node is AstNode { return node.kind === SyntaxKind.TypeAliasDeclaration; } /** @internal */ -export function isAstEnumDeclaration(node: AstNode): node is AstNode { +export function astIsEnumDeclaration(node: AstNode): node is AstNode { return node.kind === SyntaxKind.EnumDeclaration; } /** @internal */ -export function isAstModuleDeclaration(node: AstNode): node is AstNode { +export function astIsModuleDeclaration(node: AstNode): node is AstNode { return node.kind === SyntaxKind.ModuleDeclaration; } /** @internal */ -export function isAstModuleBlock(node: AstNode): node is AstNode { +export function astIsModuleBlock(node: AstNode): node is AstNode { return node.kind === SyntaxKind.ModuleBlock; } /** @internal */ -export function isAstCaseBlock(node: AstNode): node is AstNode { +export function astIsCaseBlock(node: AstNode): node is AstNode { return node.kind === SyntaxKind.CaseBlock; } /** @internal */ -export function isAstNamespaceExportDeclaration(node: AstNode): node is AstNode { +export function astIsNamespaceExportDeclaration(node: AstNode): node is AstNode { return node.kind === SyntaxKind.NamespaceExportDeclaration; } /** @internal */ -export function isAstImportEqualsDeclaration(node: AstNode): node is AstNode { +export function astIsImportEqualsDeclaration(node: AstNode): node is AstNode { return node.kind === SyntaxKind.ImportEqualsDeclaration; } /** @internal */ -export function isAstImportDeclaration(node: AstNode): node is AstNode { +export function astIsImportDeclaration(node: AstNode): node is AstNode { return node.kind === SyntaxKind.ImportDeclaration; } /** @internal */ -export function isAstImportClause(node: AstNode): node is AstNode { +export function astIsImportClause(node: AstNode): node is AstNode { return node.kind === SyntaxKind.ImportClause; } /** @internal */ -export function isAstImportTypeAssertionContainer(node: AstNode): node is AstNode { +export function astIsImportTypeAssertionContainer(node: AstNode): node is AstNode { return node.kind === SyntaxKind.ImportTypeAssertionContainer; } @@ -1010,7 +1010,7 @@ export function isAstImportTypeAssertionContainer(node: AstNode): node is AstNod * @deprecated * @internal */ -export function isAstAssertClause(node: AstNode): node is AstNode { +export function astIsAssertClause(node: AstNode): node is AstNode { return node.kind === SyntaxKind.AssertClause; } @@ -1018,203 +1018,203 @@ export function isAstAssertClause(node: AstNode): node is AstNode * @deprecated * @internal */ -export function isAstAssertEntry(node: AstNode): node is AstNode { +export function astIsAssertEntry(node: AstNode): node is AstNode { return node.kind === SyntaxKind.AssertEntry; } /** @internal */ -export function isAstImportAttributes(node: AstNode): node is AstNode { +export function astIsImportAttributes(node: AstNode): node is AstNode { return node.kind === SyntaxKind.ImportAttributes; } /** @internal */ -export function isAstImportAttribute(node: AstNode): node is AstNode { +export function astIsImportAttribute(node: AstNode): node is AstNode { return node.kind === SyntaxKind.ImportAttribute; } /** @internal */ -export function isAstNamespaceImport(node: AstNode): node is AstNode { +export function astIsNamespaceImport(node: AstNode): node is AstNode { return node.kind === SyntaxKind.NamespaceImport; } /** @internal */ -export function isAstNamespaceExport(node: AstNode): node is AstNode { +export function astIsNamespaceExport(node: AstNode): node is AstNode { return node.kind === SyntaxKind.NamespaceExport; } /** @internal */ -export function isAstNamedImports(node: AstNode): node is AstNode { +export function astIsNamedImports(node: AstNode): node is AstNode { return node.kind === SyntaxKind.NamedImports; } /** @internal */ -export function isAstImportSpecifier(node: AstNode): node is AstNode { +export function astIsImportSpecifier(node: AstNode): node is AstNode { return node.kind === SyntaxKind.ImportSpecifier; } /** @internal */ -export function isAstExportAssignment(node: AstNode): node is AstNode { +export function astIsExportAssignment(node: AstNode): node is AstNode { return node.kind === SyntaxKind.ExportAssignment; } /** @internal */ -export function isAstExportDeclaration(node: AstNode): node is AstNode { +export function astIsExportDeclaration(node: AstNode): node is AstNode { return node.kind === SyntaxKind.ExportDeclaration; } /** @internal */ -export function isAstNamedExports(node: AstNode): node is AstNode { +export function astIsNamedExports(node: AstNode): node is AstNode { return node.kind === SyntaxKind.NamedExports; } /** @internal */ -export function isAstExportSpecifier(node: AstNode): node is AstNode { +export function astIsExportSpecifier(node: AstNode): node is AstNode { return node.kind === SyntaxKind.ExportSpecifier; } /** @internal */ -export function isAstModuleExportName(node: AstNode): node is AstNode { +export function astIsModuleExportName(node: AstNode): node is AstNode { return node.kind === SyntaxKind.Identifier || node.kind === SyntaxKind.StringLiteral; } /** @internal */ -export function isAstMissingDeclaration(node: AstNode): node is AstNode { +export function astIsMissingDeclaration(node: AstNode): node is AstNode { return node.kind === SyntaxKind.MissingDeclaration; } /** @internal */ -export function isAstNotEmittedStatement(node: AstNode): node is AstNode { +export function astIsNotEmittedStatement(node: AstNode): node is AstNode { return node.kind === SyntaxKind.NotEmittedStatement; } /** @internal */ -export function isAstSyntheticReference(node: AstNode): node is AstNode { +export function astIsSyntheticReference(node: AstNode): node is AstNode { return node.kind === SyntaxKind.SyntheticReferenceExpression; } // Module References /** @internal */ -export function isAstExternalModuleReference(node: AstNode): node is AstNode { +export function astIsExternalModuleReference(node: AstNode): node is AstNode { return node.kind === SyntaxKind.ExternalModuleReference; } // JSX /** @internal */ -export function isAstJsxElement(node: AstNode): node is AstNode { +export function astIsJsxElement(node: AstNode): node is AstNode { return node.kind === SyntaxKind.JsxElement; } /** @internal */ -export function isAstJsxSelfClosingElement(node: AstNode): node is AstNode { +export function astIsJsxSelfClosingElement(node: AstNode): node is AstNode { return node.kind === SyntaxKind.JsxSelfClosingElement; } /** @internal */ -export function isAstJsxOpeningElement(node: AstNode): node is AstNode { +export function astIsJsxOpeningElement(node: AstNode): node is AstNode { return node.kind === SyntaxKind.JsxOpeningElement; } /** @internal */ -export function isAstJsxClosingElement(node: AstNode): node is AstNode { +export function astIsJsxClosingElement(node: AstNode): node is AstNode { return node.kind === SyntaxKind.JsxClosingElement; } /** @internal */ -export function isAstJsxFragment(node: AstNode): node is AstNode { +export function astIsJsxFragment(node: AstNode): node is AstNode { return node.kind === SyntaxKind.JsxFragment; } /** @internal */ -export function isAstJsxOpeningFragment(node: AstNode): node is AstNode { +export function astIsJsxOpeningFragment(node: AstNode): node is AstNode { return node.kind === SyntaxKind.JsxOpeningFragment; } /** @internal */ -export function isAstJsxClosingFragment(node: AstNode): node is AstNode { +export function astIsJsxClosingFragment(node: AstNode): node is AstNode { return node.kind === SyntaxKind.JsxClosingFragment; } /** @internal */ -export function isAstJsxAttribute(node: AstNode): node is AstNode { +export function astIsJsxAttribute(node: AstNode): node is AstNode { return node.kind === SyntaxKind.JsxAttribute; } /** @internal */ -export function isAstJsxAttributes(node: AstNode): node is AstNode { +export function astIsJsxAttributes(node: AstNode): node is AstNode { return node.kind === SyntaxKind.JsxAttributes; } /** @internal */ -export function isAstJsxSpreadAttribute(node: AstNode): node is AstNode { +export function astIsJsxSpreadAttribute(node: AstNode): node is AstNode { return node.kind === SyntaxKind.JsxSpreadAttribute; } /** @internal */ -export function isAstJsxExpression(node: AstNode): node is AstNode { +export function astIsJsxExpression(node: AstNode): node is AstNode { return node.kind === SyntaxKind.JsxExpression; } /** @internal */ -export function isAstJsxNamespacedName(node: AstNode): node is AstNode { +export function astIsJsxNamespacedName(node: AstNode): node is AstNode { return node.kind === SyntaxKind.JsxNamespacedName; } // Clauses /** @internal */ -export function isAstCaseClause(node: AstNode): node is AstNode { +export function astIsCaseClause(node: AstNode): node is AstNode { return node.kind === SyntaxKind.CaseClause; } /** @internal */ -export function isAstDefaultClause(node: AstNode): node is AstNode { +export function astIsDefaultClause(node: AstNode): node is AstNode { return node.kind === SyntaxKind.DefaultClause; } /** @internal */ -export function isAstHeritageClause(node: AstNode): node is AstNode { +export function astIsHeritageClause(node: AstNode): node is AstNode { return node.kind === SyntaxKind.HeritageClause; } /** @internal */ -export function isAstCatchClause(node: AstNode): node is AstNode { +export function astIsCatchClause(node: AstNode): node is AstNode { return node.kind === SyntaxKind.CatchClause; } // Property assignments /** @internal */ -export function isAstPropertyAssignment(node: AstNode): node is AstNode { +export function astIsPropertyAssignment(node: AstNode): node is AstNode { return node.kind === SyntaxKind.PropertyAssignment; } /** @internal */ -export function isAstShorthandPropertyAssignment(node: AstNode): node is AstNode { +export function astIsShorthandPropertyAssignment(node: AstNode): node is AstNode { return node.kind === SyntaxKind.ShorthandPropertyAssignment; } /** @internal */ -export function isAstSpreadAssignment(node: AstNode): node is AstNode { +export function astIsSpreadAssignment(node: AstNode): node is AstNode { return node.kind === SyntaxKind.SpreadAssignment; } // Enum /** @internal */ -export function isAstEnumMember(node: AstNode): node is AstNode { +export function astIsEnumMember(node: AstNode): node is AstNode { return node.kind === SyntaxKind.EnumMember; } /** @internal */ // Top-level nodes -export function isAstSourceFile(node: AstNode): node is AstNode { +export function astIsSourceFile(node: AstNode): node is AstNode { return node.kind === SyntaxKind.SourceFile; } /** @internal */ -export function isAstBundle(node: AstNode): node is AstNode { +export function astIsBundle(node: AstNode): node is AstNode { return node.kind === SyntaxKind.Bundle; } @@ -1223,228 +1223,228 @@ export function isAstBundle(node: AstNode): node is AstNode { // JSDoc Elements /** @internal */ -export function isAstJSDocTypeExpression(node: AstNode): node is AstNode { +export function astIsJSDocTypeExpression(node: AstNode): node is AstNode { return node.kind === SyntaxKind.JSDocTypeExpression; } /** @internal */ -export function isAstJSDocNameReference(node: AstNode): node is AstNode { +export function astIsJSDocNameReference(node: AstNode): node is AstNode { return node.kind === SyntaxKind.JSDocNameReference; } /** @internal */ -export function isAstJSDocMemberName(node: AstNode): node is AstNode { +export function astIsJSDocMemberName(node: AstNode): node is AstNode { return node.kind === SyntaxKind.JSDocMemberName; } /** @internal */ -export function isAstJSDocLink(node: AstNode): node is AstNode { +export function astIsJSDocLink(node: AstNode): node is AstNode { return node.kind === SyntaxKind.JSDocLink; } /** @internal */ -export function isAstJSDocLinkCode(node: AstNode): node is AstNode { +export function astIsJSDocLinkCode(node: AstNode): node is AstNode { return node.kind === SyntaxKind.JSDocLinkCode; } /** @internal */ -export function isAstJSDocLinkPlain(node: AstNode): node is AstNode { +export function astIsJSDocLinkPlain(node: AstNode): node is AstNode { return node.kind === SyntaxKind.JSDocLinkPlain; } /** @internal */ -export function isAstJSDocAllType(node: AstNode): node is AstNode { +export function astIsJSDocAllType(node: AstNode): node is AstNode { return node.kind === SyntaxKind.JSDocAllType; } /** @internal */ -export function isAstJSDocUnknownType(node: AstNode): node is AstNode { +export function astIsJSDocUnknownType(node: AstNode): node is AstNode { return node.kind === SyntaxKind.JSDocUnknownType; } /** @internal */ -export function isAstJSDocNullableType(node: AstNode): node is AstNode { +export function astIsJSDocNullableType(node: AstNode): node is AstNode { return node.kind === SyntaxKind.JSDocNullableType; } /** @internal */ -export function isAstJSDocNonNullableType(node: AstNode): node is AstNode { +export function astIsJSDocNonNullableType(node: AstNode): node is AstNode { return node.kind === SyntaxKind.JSDocNonNullableType; } /** @internal */ -export function isAstJSDocOptionalType(node: AstNode): node is AstNode { +export function astIsJSDocOptionalType(node: AstNode): node is AstNode { return node.kind === SyntaxKind.JSDocOptionalType; } /** @internal */ -export function isAstJSDocFunctionType(node: AstNode): node is AstNode { +export function astIsJSDocFunctionType(node: AstNode): node is AstNode { return node.kind === SyntaxKind.JSDocFunctionType; } /** @internal */ -export function isAstJSDocVariadicType(node: AstNode): node is AstNode { +export function astIsJSDocVariadicType(node: AstNode): node is AstNode { return node.kind === SyntaxKind.JSDocVariadicType; } /** @internal */ -export function isAstJSDocNamepathType(node: AstNode): node is AstNode { +export function astIsJSDocNamepathType(node: AstNode): node is AstNode { return node.kind === SyntaxKind.JSDocNamepathType; } /** @internal */ -export function isAstJSDoc(node: AstNode): node is AstNode { +export function astIsJSDoc(node: AstNode): node is AstNode { return node.kind === SyntaxKind.JSDoc; } /** @internal */ -export function isAstJSDocTypeLiteral(node: AstNode): node is AstNode { +export function astIsJSDocTypeLiteral(node: AstNode): node is AstNode { return node.kind === SyntaxKind.JSDocTypeLiteral; } /** @internal */ -export function isAstJSDocSignature(node: AstNode): node is AstNode { +export function astIsJSDocSignature(node: AstNode): node is AstNode { return node.kind === SyntaxKind.JSDocSignature; } // JSDoc Tags /** @internal */ -export function isAstJSDocAugmentsTag(node: AstNode): node is AstNode { +export function astIsJSDocAugmentsTag(node: AstNode): node is AstNode { return node.kind === SyntaxKind.JSDocAugmentsTag; } /** @internal */ -export function isAstJSDocAuthorTag(node: AstNode): node is AstNode { +export function astIsJSDocAuthorTag(node: AstNode): node is AstNode { return node.kind === SyntaxKind.JSDocAuthorTag; } /** @internal */ -export function isAstJSDocClassTag(node: AstNode): node is AstNode { +export function astIsJSDocClassTag(node: AstNode): node is AstNode { return node.kind === SyntaxKind.JSDocClassTag; } /** @internal */ -export function isAstJSDocCallbackTag(node: AstNode): node is AstNode { +export function astIsJSDocCallbackTag(node: AstNode): node is AstNode { return node.kind === SyntaxKind.JSDocCallbackTag; } /** @internal */ -export function isAstJSDocPublicTag(node: AstNode): node is AstNode { +export function astIsJSDocPublicTag(node: AstNode): node is AstNode { return node.kind === SyntaxKind.JSDocPublicTag; } /** @internal */ -export function isAstJSDocPrivateTag(node: AstNode): node is AstNode { +export function astIsJSDocPrivateTag(node: AstNode): node is AstNode { return node.kind === SyntaxKind.JSDocPrivateTag; } /** @internal */ -export function isAstJSDocProtectedTag(node: AstNode): node is AstNode { +export function astIsJSDocProtectedTag(node: AstNode): node is AstNode { return node.kind === SyntaxKind.JSDocProtectedTag; } /** @internal */ -export function isAstJSDocReadonlyTag(node: AstNode): node is AstNode { +export function astIsJSDocReadonlyTag(node: AstNode): node is AstNode { return node.kind === SyntaxKind.JSDocReadonlyTag; } /** @internal */ -export function isAstJSDocOverrideTag(node: AstNode): node is AstNode { +export function astIsJSDocOverrideTag(node: AstNode): node is AstNode { return node.kind === SyntaxKind.JSDocOverrideTag; } /** @internal */ -export function isAstJSDocOverloadTag(node: AstNode): node is AstNode { +export function astIsJSDocOverloadTag(node: AstNode): node is AstNode { return node.kind === SyntaxKind.JSDocOverloadTag; } /** @internal */ -export function isAstJSDocDeprecatedTag(node: AstNode): node is AstNode { +export function astIsJSDocDeprecatedTag(node: AstNode): node is AstNode { return node.kind === SyntaxKind.JSDocDeprecatedTag; } /** @internal */ -export function isAstJSDocSeeTag(node: AstNode): node is AstNode { +export function astIsJSDocSeeTag(node: AstNode): node is AstNode { return node.kind === SyntaxKind.JSDocSeeTag; } /** @internal */ -export function isAstJSDocEnumTag(node: AstNode): node is AstNode { +export function astIsJSDocEnumTag(node: AstNode): node is AstNode { return node.kind === SyntaxKind.JSDocEnumTag; } /** @internal */ -export function isAstJSDocParameterTag(node: AstNode): node is AstNode { +export function astIsJSDocParameterTag(node: AstNode): node is AstNode { return node.kind === SyntaxKind.JSDocParameterTag; } /** @internal */ -export function isAstJSDocReturnTag(node: AstNode): node is AstNode { +export function astIsJSDocReturnTag(node: AstNode): node is AstNode { return node.kind === SyntaxKind.JSDocReturnTag; } /** @internal */ -export function isAstJSDocThisTag(node: AstNode): node is AstNode { +export function astIsJSDocThisTag(node: AstNode): node is AstNode { return node.kind === SyntaxKind.JSDocThisTag; } /** @internal */ -export function isAstJSDocTypeTag(node: AstNode): node is AstNode { +export function astIsJSDocTypeTag(node: AstNode): node is AstNode { return node.kind === SyntaxKind.JSDocTypeTag; } /** @internal */ -export function isAstJSDocTemplateTag(node: AstNode): node is AstNode { +export function astIsJSDocTemplateTag(node: AstNode): node is AstNode { return node.kind === SyntaxKind.JSDocTemplateTag; } /** @internal */ -export function isAstJSDocTypedefTag(node: AstNode): node is AstNode { +export function astIsJSDocTypedefTag(node: AstNode): node is AstNode { return node.kind === SyntaxKind.JSDocTypedefTag; } /** @internal */ -export function isAstJSDocUnknownTag(node: AstNode): node is AstNode { +export function astIsJSDocUnknownTag(node: AstNode): node is AstNode { return node.kind === SyntaxKind.JSDocTag; } /** @internal */ -export function isAstJSDocPropertyTag(node: AstNode): node is AstNode { +export function astIsJSDocPropertyTag(node: AstNode): node is AstNode { return node.kind === SyntaxKind.JSDocPropertyTag; } /** @internal */ -export function isAstJSDocImplementsTag(node: AstNode): node is AstNode { +export function astIsJSDocImplementsTag(node: AstNode): node is AstNode { return node.kind === SyntaxKind.JSDocImplementsTag; } /** @internal */ -export function isAstJSDocSatisfiesTag(node: AstNode): node is AstNode { +export function astIsJSDocSatisfiesTag(node: AstNode): node is AstNode { return node.kind === SyntaxKind.JSDocSatisfiesTag; } /** @internal */ -export function isAstJSDocThrowsTag(node: AstNode): node is AstNode { +export function astIsJSDocThrowsTag(node: AstNode): node is AstNode { return node.kind === SyntaxKind.JSDocThrowsTag; } /** @internal */ -export function isAstJSDocImportTag(node: AstNode): node is AstNode { +export function astIsJSDocImportTag(node: AstNode): node is AstNode { return node.kind === SyntaxKind.JSDocImportTag; } // Synthesized list /** @internal */ -export function isAstSyntaxList(n: Node): n is SyntaxList { +export function astIsSyntaxList(n: Node): n is SyntaxList { return n.kind === SyntaxKind.SyntaxList; } // Unions /** @internal */ -export function isAstPropertyName(node: AstNode): node is AstPropertyName { +export function astIsPropertyName(node: AstNode): node is AstPropertyName { const kind = node.kind; return kind === SyntaxKind.Identifier || kind === SyntaxKind.PrivateIdentifier @@ -1454,27 +1454,27 @@ export function isAstPropertyName(node: AstNode): node is AstPropertyName { } /** @internal */ -export function isAstPropertyAccessChain(node: AstNode): node is AstPropertyAccessChain { - return isAstPropertyAccessExpression(node) && !!(node.flags & NodeFlags.OptionalChain); +export function astIsPropertyAccessChain(node: AstNode): node is AstPropertyAccessChain { + return astIsPropertyAccessExpression(node) && !!(node.flags & NodeFlags.OptionalChain); } /** @internal */ -export function isAstElementAccessChain(node: AstNode): node is AstElementAccessChain { - return isAstElementAccessExpression(node) && !!(node.flags & NodeFlags.OptionalChain); +export function astIsElementAccessChain(node: AstNode): node is AstElementAccessChain { + return astIsElementAccessExpression(node) && !!(node.flags & NodeFlags.OptionalChain); } /** @internal */ -export function isAstCallChain(node: AstNode): node is AstCallChain { - return isAstCallExpression(node) && !!(node.flags & NodeFlags.OptionalChain); +export function astIsCallChain(node: AstNode): node is AstCallChain { + return astIsCallExpression(node) && !!(node.flags & NodeFlags.OptionalChain); } /** @internal */ -export function isAstNonNullChain(node: AstNode): node is AstNonNullChain { - return isAstNonNullExpression(node) && !!(node.flags & NodeFlags.OptionalChain); +export function astIsNonNullChain(node: AstNode): node is AstNonNullChain { + return astIsNonNullExpression(node) && !!(node.flags & NodeFlags.OptionalChain); } /** @internal */ -export function isAstOptionalChain(node: AstNode): node is AstPropertyAccessChain | AstElementAccessChain | AstCallChain | AstNonNullChain { +export function astIsOptionalChain(node: AstNode): node is AstPropertyAccessChain | AstElementAccessChain | AstCallChain | AstNonNullChain { const kind = node.kind; return !!(node.flags & NodeFlags.OptionalChain) && (kind === SyntaxKind.PropertyAccessExpression @@ -1484,22 +1484,22 @@ export function isAstOptionalChain(node: AstNode): node is AstPropertyAccessChai } /** @internal */ -export function isAstOptionalChainRoot(node: AstNode): node is AstOptionalChainRoot { - return isAstOptionalChain(node) && !isAstNonNullExpression(node) && !!node.data.questionDotToken; +export function astIsOptionalChainRoot(node: AstNode): node is AstOptionalChainRoot { + return astIsOptionalChain(node) && !astIsNonNullExpression(node) && !!node.data.questionDotToken; } /** @internal */ -export function isAstLeftHandSideExpression(node: AstNode): node is AstLeftHandSideExpression { - return isLeftHandSideExpressionKind(skipAstOuterExpressions(node, OuterExpressionKinds.PartiallyEmittedExpressions).kind); +export function astIsLeftHandSideExpression(node: AstNode): node is AstLeftHandSideExpression { + return isLeftHandSideExpressionKind(astSkipOuterExpressions(node, OuterExpressionKinds.PartiallyEmittedExpressions).kind); } /** @internal */ -export function isAstStringOrNumericLiteralLike(node: AstNode): node is AstStringLiteralLike | AstNumericLiteral { - return isAstStringLiteralLike(node) || isAstNumericLiteral(node); +export function astIsStringOrNumericLiteralLike(node: AstNode): node is AstStringLiteralLike | AstNumericLiteral { + return astIsStringLiteralLike(node) || astIsNumericLiteral(node); } /** @internal */ -export function isAstStringLiteralLike(node: AstNode): node is AstStringLiteralLike { +export function astIsStringLiteralLike(node: AstNode): node is AstStringLiteralLike { return node.kind === SyntaxKind.StringLiteral || node.kind === SyntaxKind.NoSubstitutionTemplateLiteral; } @@ -1516,43 +1516,6 @@ export function astHasJSDocNodes(node: AstNode): node is AstHasJSDoc { } /** @internal */ -export function astCanHaveModifiers(node: AstNode): node is AstHasModifiers { - const kind = node.kind; - return kind === SyntaxKind.TypeParameter - || kind === SyntaxKind.Parameter - || kind === SyntaxKind.PropertySignature - || kind === SyntaxKind.PropertyDeclaration - || kind === SyntaxKind.MethodSignature - || kind === SyntaxKind.MethodDeclaration - || kind === SyntaxKind.Constructor - || kind === SyntaxKind.GetAccessor - || kind === SyntaxKind.SetAccessor - || kind === SyntaxKind.IndexSignature - || kind === SyntaxKind.ConstructorType - || kind === SyntaxKind.FunctionExpression - || kind === SyntaxKind.ArrowFunction - || kind === SyntaxKind.ClassExpression - || kind === SyntaxKind.VariableStatement - || kind === SyntaxKind.FunctionDeclaration - || kind === SyntaxKind.ClassDeclaration - || kind === SyntaxKind.InterfaceDeclaration - || kind === SyntaxKind.TypeAliasDeclaration - || kind === SyntaxKind.EnumDeclaration - || kind === SyntaxKind.ModuleDeclaration - || kind === SyntaxKind.ImportEqualsDeclaration - || kind === SyntaxKind.ImportDeclaration - || kind === SyntaxKind.ExportAssignment - || kind === SyntaxKind.ExportDeclaration; -} - -/** @internal */ -export function astCanHaveDecorators(node: AstNode): node is AstHasDecorators { - const kind = node.kind; - return kind === SyntaxKind.Parameter - || kind === SyntaxKind.PropertyDeclaration - || kind === SyntaxKind.MethodDeclaration - || kind === SyntaxKind.GetAccessor - || kind === SyntaxKind.SetAccessor - || kind === SyntaxKind.ClassExpression - || kind === SyntaxKind.ClassDeclaration; +export function astIsExpression(node: AstNode): node is AstExpression { + return isExpressionKind(astSkipOuterExpressions(node, OuterExpressionKinds.PartiallyEmittedExpressions).kind); } diff --git a/src/compiler/factory/astParenthesizerRules.ts b/src/compiler/factory/astParenthesizerRules.ts index a57fd4bfdf8..7f24303422d 100644 --- a/src/compiler/factory/astParenthesizerRules.ts +++ b/src/compiler/factory/astParenthesizerRules.ts @@ -21,21 +21,20 @@ import { AstTaggedTemplateExpression, AstTypeNode, AstUnaryExpression, - isAstBinaryExpression, - isAstBlock, - isAstCallExpression, - isAstCommaListExpression, - isAstConditionalTypeNode, - isAstConstructorTypeNode, - isAstFunctionTypeNode, - isAstInferTypeNode, - isAstIntersectionTypeNode, - isAstJSDocNullableType, - isAstNamedTupleMember, - isAstOptionalChain, - isAstTypeOperatorNode, - isAstUnionTypeNode, - skipAstOuterExpressions, + astIsBinaryExpression, + astIsBlock, + astIsCallExpression, + astIsCommaListExpression, + astIsConditionalTypeNode, + astIsConstructorTypeNode, + astIsFunctionTypeNode, + astIsInferTypeNode, + astIsIntersectionTypeNode, + astIsJSDocNullableType, + astIsNamedTupleMember, + astIsOptionalChain, + astIsTypeOperatorNode, + astIsUnionTypeNode, Associativity, BinaryOperator, compareValues, @@ -56,6 +55,7 @@ import { setTextRange, SyntaxKind, TextRange, + astSkipOuterExpressions, } from "../_namespaces/ts.js"; /** @internal */ @@ -179,7 +179,7 @@ export function createAstParenthesizerRules(factory: AstNodeFactory): AstParenth // the intended order of operations: `(a ** b) ** c` const binaryOperatorPrecedence = getOperatorPrecedence(SyntaxKind.BinaryExpression, binaryOperator); const binaryOperatorAssociativity = getOperatorAssociativity(SyntaxKind.BinaryExpression, binaryOperator); - const emittedOperand = skipAstOuterExpressions(operand, OuterExpressionKinds.PartiallyEmittedExpressions) as AstExpression; + const emittedOperand = astSkipOuterExpressions(operand, OuterExpressionKinds.PartiallyEmittedExpressions); if (!isLeftSideOfBinary && operand.kind === SyntaxKind.ArrowFunction && binaryOperatorPrecedence > OperatorPrecedence.Assignment) { // We need to parenthesize arrow functions on the right side to avoid it being // parsed as parenthesized expression: `a && (() => {})` @@ -218,7 +218,7 @@ export function createAstParenthesizerRules(factory: AstNodeFactory): AstParenth } else { if ( - isAstBinaryExpression(emittedOperand) + astIsBinaryExpression(emittedOperand) && emittedOperand.data.operatorToken.kind === binaryOperator ) { // No need to parenthesize the right operand when the binary operator and @@ -289,13 +289,13 @@ export function createAstParenthesizerRules(factory: AstNodeFactory): AstParenth * emitted without parentheses. */ function getLiteralKindOfBinaryPlusOperand(node: AstExpression): SyntaxKind { - node = skipAstOuterExpressions(node, OuterExpressionKinds.PartiallyEmittedExpressions) as AstExpression; + node = astSkipOuterExpressions(node, OuterExpressionKinds.PartiallyEmittedExpressions); if (isLiteralKind(node.kind)) { return node.kind; } - if (isAstBinaryExpression(node) && (node as AstBinaryExpression).data.operatorToken.kind === SyntaxKind.PlusToken) { + if (astIsBinaryExpression(node) && (node as AstBinaryExpression).data.operatorToken.kind === SyntaxKind.PlusToken) { if (node.data.cachedLiteralKind !== undefined) { return node.data.cachedLiteralKind; } @@ -323,7 +323,7 @@ export function createAstParenthesizerRules(factory: AstNodeFactory): AstParenth * BinaryExpression. */ function parenthesizeBinaryOperand(binaryOperator: SyntaxKind, operand: AstExpression, isLeftSideOfBinary: boolean, leftOperand?: AstExpression) { - const skipped = skipAstOuterExpressions(operand, OuterExpressionKinds.PartiallyEmittedExpressions) as AstExpression; + const skipped = astSkipOuterExpressions(operand, OuterExpressionKinds.PartiallyEmittedExpressions); // If the resulting expression is already parenthesized, we do not need to do any further processing. if (skipped.kind === SyntaxKind.ParenthesizedExpression) { @@ -349,7 +349,7 @@ export function createAstParenthesizerRules(factory: AstNodeFactory): AstParenth function parenthesizeConditionOfConditionalExpression(condition: AstExpression): AstExpression { const conditionalPrecedence = getOperatorPrecedence(SyntaxKind.ConditionalExpression, SyntaxKind.QuestionToken); - const emittedCondition = skipAstOuterExpressions(condition, OuterExpressionKinds.PartiallyEmittedExpressions) as AstExpression; + const emittedCondition = astSkipOuterExpressions(condition, OuterExpressionKinds.PartiallyEmittedExpressions); const conditionPrecedence = getExpressionPrecedence(emittedCondition); if (compareValues(conditionPrecedence, conditionalPrecedence) !== Comparison.GreaterThan) { return factory.createParenthesizedExpression(condition); @@ -358,14 +358,14 @@ export function createAstParenthesizerRules(factory: AstNodeFactory): AstParenth } function isCommaSequence(expression: AstExpression): boolean { - return isAstCommaListExpression(expression) || isAstBinaryExpression(expression) && expression.node.data.operatorToken.kind === SyntaxKind.CommaToken; + return astIsCommaListExpression(expression) || astIsBinaryExpression(expression) && expression.node.data.operatorToken.kind === SyntaxKind.CommaToken; } function parenthesizeBranchOfConditionalExpression(branch: AstExpression): AstExpression { // per ES grammar both 'whenTrue' and 'whenFalse' parts of conditional expression are assignment expressions // so in case when comma expression is introduced as a part of previous transformations // if should be wrapped in parens since comma operator has the lowest precedence - const emittedExpression = skipAstOuterExpressions(branch, OuterExpressionKinds.PartiallyEmittedExpressions) as AstExpression; + const emittedExpression = astSkipOuterExpressions(branch, OuterExpressionKinds.PartiallyEmittedExpressions); return isCommaSequence(emittedExpression) ? factory.createParenthesizedExpression(branch) : branch; @@ -383,7 +383,7 @@ export function createAstParenthesizerRules(factory: AstNodeFactory): AstParenth * - ClassExpression */ function parenthesizeExpressionOfExportDefault(expression: AstExpression): AstExpression { - const check = skipAstOuterExpressions(expression, OuterExpressionKinds.PartiallyEmittedExpressions) as AstExpression; + const check = astSkipOuterExpressions(expression, OuterExpressionKinds.PartiallyEmittedExpressions); let needsParens = isCommaSequence(check); if (!needsParens) { switch (getLeftmostExpression(check, /*stopAtCallExpressions*/ false).kind) { @@ -425,11 +425,11 @@ export function createAstParenthesizerRules(factory: AstNodeFactory): AstParenth // NewExpression: // new C.x -> not the same as (new C).x // - const emittedExpression = skipAstOuterExpressions(expression, OuterExpressionKinds.PartiallyEmittedExpressions) as AstExpression; + const emittedExpression = astSkipOuterExpressions(expression, OuterExpressionKinds.PartiallyEmittedExpressions); if ( - isLeftHandSideExpressionKind(skipAstOuterExpressions(emittedExpression, OuterExpressionKinds.PartiallyEmittedExpressions).kind) + isLeftHandSideExpressionKind(astSkipOuterExpressions(emittedExpression, OuterExpressionKinds.PartiallyEmittedExpressions).kind) && (emittedExpression.kind !== SyntaxKind.NewExpression || (emittedExpression as AstNewExpression).data.arguments) - && (optionalChain || !isAstOptionalChain(emittedExpression)) + && (optionalChain || !astIsOptionalChain(emittedExpression)) ) { // TODO(rbuckton): Verify whether this assertion holds. return expression as AstLeftHandSideExpression; @@ -441,12 +441,12 @@ export function createAstParenthesizerRules(factory: AstNodeFactory): AstParenth function parenthesizeOperandOfPostfixUnary(operand: AstExpression): AstLeftHandSideExpression { // TODO(rbuckton): Verifiy whether `setTextRange` is needed. - return isLeftHandSideExpressionKind(skipAstOuterExpressions(operand, OuterExpressionKinds.PartiallyEmittedExpressions).kind) ? operand as AstLeftHandSideExpression : setTextRange(factory.createParenthesizedExpression(operand), operand); + return isLeftHandSideExpressionKind(astSkipOuterExpressions(operand, OuterExpressionKinds.PartiallyEmittedExpressions).kind) ? operand as AstLeftHandSideExpression : setTextRange(factory.createParenthesizedExpression(operand), operand); } function parenthesizeOperandOfPrefixUnary(operand: AstExpression): AstUnaryExpression { // TODO(rbuckton): Verifiy whether `setTextRange` is needed. - return isUnaryExpressionKind(skipAstOuterExpressions(operand, OuterExpressionKinds.PartiallyEmittedExpressions).kind) ? operand as AstUnaryExpression : setTextRange(factory.createParenthesizedExpression(operand), operand); + return isUnaryExpressionKind(astSkipOuterExpressions(operand, OuterExpressionKinds.PartiallyEmittedExpressions).kind) ? operand as AstUnaryExpression : setTextRange(factory.createParenthesizedExpression(operand), operand); } function parenthesizeExpressionsOfCommaDelimitedList(elements: AstNodeArrayLike): AstNodeArray { @@ -466,7 +466,7 @@ export function createAstParenthesizerRules(factory: AstNodeFactory): AstParenth } function parenthesizeExpressionForDisallowedComma(expression: AstExpression): AstExpression { - const emittedExpression = skipAstOuterExpressions(expression, OuterExpressionKinds.PartiallyEmittedExpressions) as AstExpression; + const emittedExpression = astSkipOuterExpressions(expression, OuterExpressionKinds.PartiallyEmittedExpressions); const expressionPrecedence = getExpressionPrecedence(emittedExpression); const commaPrecedence = getOperatorPrecedence(SyntaxKind.BinaryExpression, SyntaxKind.CommaToken); // TODO(rbuckton): Verifiy whether `setTextRange` is needed. @@ -474,10 +474,10 @@ export function createAstParenthesizerRules(factory: AstNodeFactory): AstParenth } function parenthesizeExpressionOfExpressionStatement(expression: AstExpression): AstExpression { - const emittedExpression = skipAstOuterExpressions(expression, OuterExpressionKinds.PartiallyEmittedExpressions) as AstExpression; - if (isAstCallExpression(emittedExpression)) { + const emittedExpression = astSkipOuterExpressions(expression, OuterExpressionKinds.PartiallyEmittedExpressions); + if (astIsCallExpression(emittedExpression)) { const callee = emittedExpression.data.expression; - const kind = skipAstOuterExpressions(callee, OuterExpressionKinds.PartiallyEmittedExpressions).kind; + const kind = astSkipOuterExpressions(callee, OuterExpressionKinds.PartiallyEmittedExpressions).kind; if (kind === SyntaxKind.FunctionExpression || kind === SyntaxKind.ArrowFunction) { // TODO(rbuckton): Verifiy whether `setTextRange` is needed. const updated = factory.updateCallExpression( @@ -502,7 +502,7 @@ export function createAstParenthesizerRules(factory: AstNodeFactory): AstParenth function parenthesizeConciseBodyOfArrowFunction(body: AstExpression): AstExpression; function parenthesizeConciseBodyOfArrowFunction(body: AstConciseBody): AstConciseBody; function parenthesizeConciseBodyOfArrowFunction(body: AstConciseBody): AstConciseBody { - if (!isAstBlock(body) && (isCommaSequence(body) || getLeftmostExpression(body, /*stopAtCallExpressions*/ false).kind === SyntaxKind.ObjectLiteralExpression)) { + if (!astIsBlock(body) && (isCommaSequence(body) || getLeftmostExpression(body, /*stopAtCallExpressions*/ false).kind === SyntaxKind.ObjectLiteralExpression)) { // TODO(rbuckton): Verifiy whether `setTextRange` is needed. return setTextRange(factory.createParenthesizedExpression(body), body); } @@ -660,13 +660,13 @@ export function createAstParenthesizerRules(factory: AstNodeFactory): AstParenth } function hasJSDocPostfixQuestion(type: AstTypeNode | AstNamedTupleMember): boolean { - if (isAstJSDocNullableType(type)) return type.data.postfix; - if (isAstNamedTupleMember(type)) return hasJSDocPostfixQuestion(type.data.type); - if (isAstFunctionTypeNode(type) || isAstConstructorTypeNode(type) || isAstTypeOperatorNode(type)) return hasJSDocPostfixQuestion(type.data.type); - if (isAstConditionalTypeNode(type)) return hasJSDocPostfixQuestion(type.data.falseType); - if (isAstUnionTypeNode(type)) return hasJSDocPostfixQuestion(last(type.data.types.items)); - if (isAstIntersectionTypeNode(type)) return hasJSDocPostfixQuestion(last(type.data.types.items)); - if (isAstInferTypeNode(type)) return !!type.data.typeParameter.data.constraint && hasJSDocPostfixQuestion(type.data.typeParameter.data.constraint); + if (astIsJSDocNullableType(type)) return type.data.postfix; + if (astIsNamedTupleMember(type)) return hasJSDocPostfixQuestion(type.data.type); + if (astIsFunctionTypeNode(type) || astIsConstructorTypeNode(type) || astIsTypeOperatorNode(type)) return hasJSDocPostfixQuestion(type.data.type); + if (astIsConditionalTypeNode(type)) return hasJSDocPostfixQuestion(type.data.falseType); + if (astIsUnionTypeNode(type)) return hasJSDocPostfixQuestion(last(type.data.types.items)); + if (astIsIntersectionTypeNode(type)) return hasJSDocPostfixQuestion(last(type.data.types.items)); + if (astIsInferTypeNode(type)) return !!type.data.typeParameter.data.constraint && hasJSDocPostfixQuestion(type.data.typeParameter.data.constraint); return false; } @@ -697,7 +697,7 @@ export function createAstParenthesizerRules(factory: AstNodeFactory): AstParenth // } function parenthesizeLeadingTypeArgument(node: AstTypeNode) { - return (isAstFunctionTypeNode(node) || isAstConstructorTypeNode(node)) && node.data.typeParameters ? factory.createParenthesizedType(node) : node; + return (astIsFunctionTypeNode(node) || astIsConstructorTypeNode(node)) && node.data.typeParameters ? factory.createParenthesizedType(node) : node; } function parenthesizeOrdinalTypeArgument(node: AstTypeNode, i: number) { diff --git a/src/compiler/factory/nodeTests.ts b/src/compiler/factory/nodeTests.ts index ba20a858f5b..98b2a49c3ed 100644 --- a/src/compiler/factory/nodeTests.ts +++ b/src/compiler/factory/nodeTests.ts @@ -289,7 +289,7 @@ export function isMinusToken(node: Node): node is MinusToken { return node.kind === SyntaxKind.MinusToken; } -export function isAsteriskToken(node: Node): node is AsteriskToken { +export function astIseriskToken(node: Node): node is AsteriskToken { return node.kind === SyntaxKind.AsteriskToken; } diff --git a/src/compiler/factory/utilities.ts b/src/compiler/factory/utilities.ts index 43d7bfa0178..d4ce2c4a71c 100644 --- a/src/compiler/factory/utilities.ts +++ b/src/compiler/factory/utilities.ts @@ -8,6 +8,11 @@ import { AssignmentExpression, AssignmentOperatorOrHigher, AssignmentPattern, + AstExpression, + astIsJSDocTypeAssertion, + AstNode, + AstOuterExpression, + AstWrappedExpression, BinaryExpression, BinaryOperator, BinaryOperatorToken, @@ -628,9 +633,14 @@ export function getJSDocTypeAssertionType(node: JSDocTypeAssertion): TypeNode { /** @internal */ export function isOuterExpression(node: Node, kinds: OuterExpressionKinds = OuterExpressionKinds.All): node is OuterExpression { + return astIsOuterExpression(node.ast, kinds); +} + +/** @internal */ +export function astIsOuterExpression(node: AstNode, kinds: OuterExpressionKinds = OuterExpressionKinds.All): node is AstOuterExpression { switch (node.kind) { case SyntaxKind.ParenthesizedExpression: - if (kinds & OuterExpressionKinds.ExcludeJSDocTypeAssertion && isJSDocTypeAssertion(node)) { + if (kinds & OuterExpressionKinds.ExcludeJSDocTypeAssertion && astIsJSDocTypeAssertion(node)) { return false; } return (kinds & OuterExpressionKinds.Parentheses) !== 0; @@ -656,8 +666,19 @@ export function skipOuterExpressions(node: Expression, kinds?: OuterExpressionKi export function skipOuterExpressions(node: Node, kinds?: OuterExpressionKinds): Node; /** @internal */ export function skipOuterExpressions(node: Node, kinds = OuterExpressionKinds.All) { - while (isOuterExpression(node, kinds)) { - node = node.expression; + return astSkipOuterExpressions(node.ast, kinds).node; +} + +/** @internal */ +export function astSkipOuterExpressions(node: AstWrappedExpression): T; +/** @internal */ +export function astSkipOuterExpressions(node: AstExpression, kinds?: OuterExpressionKinds): AstExpression; +/** @internal */ +export function astSkipOuterExpressions(node: AstNode, kinds?: OuterExpressionKinds): AstNode; +/** @internal */ +export function astSkipOuterExpressions(node: AstNode, kinds: OuterExpressionKinds = OuterExpressionKinds.All): AstNode { + while (astIsOuterExpression(node, kinds)) { + node = node.data.expression; } return node; } diff --git a/src/compiler/nodes.ts b/src/compiler/nodes.ts index 9e2a506f06b..3cdeacfdeca 100644 --- a/src/compiler/nodes.ts +++ b/src/compiler/nodes.ts @@ -1,3 +1,4 @@ +/* eslint-disable @typescript-eslint/naming-convention */ import { ArrayBindingPattern, ArrayLiteralExpression, @@ -52,13 +53,35 @@ import { FunctionExpression, FunctionTypeNode, GetAccessorDeclaration, + HasAsteriskToken, + HasBody, + HasComment, + HasElements, + HasEndFlowNode, + HasExclamationToken, + HasExpression, + HasInitializer, + HasIsTypeOnly, HasJSDoc, HasLocals, + HasMembers, HasName, + HasParameters, + HasQuestionDotToken, + HasQuestionToken, + HasStatement, + HasStatements, + HasSymbol, + HasTagName, + HasText, + HasType, + HasTypeParameters, + HasTypes, HeritageClause, Identifier, IfStatement, ImportAttribute, + ImportAttributes, ImportClause, ImportDeclaration, ImportEqualsDeclaration, @@ -70,6 +93,7 @@ import { IndexSignatureDeclaration, InferTypeNode, InterfaceDeclaration, + InternalHasTypeArguments, IntersectionTypeNode, IsFunctionLike, JSDoc, @@ -144,6 +168,7 @@ import { NamespaceExportDeclaration, NamespaceImport, NewExpression, + Node, NonNullExpression, NoSubstitutionTemplateLiteral, NotEmittedStatement, @@ -213,7 +238,6 @@ import { } from "./_namespaces/ts.js"; { - // eslint-disable-next-line @typescript-eslint/naming-convention type _ = [ __Expect>, __Expect, IsFunctionLike>, @@ -221,7 +245,6 @@ import { } { - // eslint-disable-next-line @typescript-eslint/naming-convention type _ = [ __Expect>, __Expect, HasLocals>, @@ -229,7 +252,6 @@ import { } { - // eslint-disable-next-line @typescript-eslint/naming-convention type _ = [ __Expect>, __Expect, HasName>, @@ -237,13 +259,195 @@ import { } { - // eslint-disable-next-line @typescript-eslint/naming-convention type _ = [ __Expect>, __Expect, HasJSDoc>, ]; } +{ + type _ = [ + __Expect>, + __Expect, HasExpression>, + ]; +} + +{ + type _ = [ + __Expect>, + __Expect, HasInitializer>, + ]; + type __ = Exclude, HasInitializer>; +} + +{ + type _ = [ + __Expect>, + __Expect, HasText>, + ]; + type __ = Exclude, HasText>; +} + +{ + type _ = [ + __Expect, { symbol: never }>>, + __Expect, { symbol: never }>, HasSymbol>, + ]; + type __ = Exclude, { symbol: never }>, HasSymbol>; +} + +{ + type _ = [ + __Expect>, + __Expect, HasType>, + ]; + type __ = Exclude, HasType>; +} + +{ + type _ = [ + __Expect>, + __Expect, HasLocals>, + ]; + type __ = Exclude, HasLocals>; +} + +{ + type _ = [ + __Expect>, + __Expect, HasTypeParameters>, + ]; + type __ = Exclude, HasTypeParameters>; +} + +{ + type _ = [ + __Expect>, + __Expect, HasParameters>, + ]; + type __ = Exclude, HasParameters>; +} + +{ + type _ = [ + __Expect>, + __Expect, HasBody>, + ]; + type __ = Exclude, HasBody>; +} + +{ + type _ = [ + __Expect>, + __Expect, HasQuestionToken>, + ]; + type __ = Exclude, HasQuestionToken>; +} + +{ + type _ = [ + __Expect>, + __Expect, HasEndFlowNode>, + ]; + type __ = Exclude, HasEndFlowNode>; +} + +{ + type _ = [ + __Expect>, + __Expect, InternalHasTypeArguments>, + ]; + type __ = Exclude, InternalHasTypeArguments>; +} + +{ + type _ = [ + __Expect>, + __Expect, HasElements>, + ]; + type __ = Exclude, HasElements>; +} + +{ + type _ = [ + __Expect>, + __Expect, HasMembers>, + ]; + type __ = Exclude, HasMembers>; +} + +{ + type _ = [ + __Expect>, + __Expect, HasStatement>, + ]; + type __ = Exclude, HasStatement>; +} + +{ + type _ = [ + __Expect>, + __Expect, HasStatements>, + ]; + type __ = Exclude, HasStatements>; +} + +{ + type _ = [ + __Expect>, + __Expect, HasExclamationToken>, + ]; + type __ = Exclude, HasExclamationToken>; +} + +{ + type _ = [ + __Expect>, + __Expect, HasAsteriskToken>, + ]; + type __ = Exclude, HasAsteriskToken>; +} + +{ + type _ = [ + __Expect>, + __Expect, HasQuestionDotToken>, + ]; + type __ = Exclude, HasQuestionDotToken>; +} + +{ + type _ = [ + __Expect>, + __Expect, HasComment>, + ]; + type __ = Exclude, HasComment>; +} + +{ + type _ = [ + __Expect>, + __Expect, HasTypes>, + ]; + type __ = Exclude, HasTypes>; +} + +{ + type _ = [ + __Expect>, + __Expect, HasTagName>, + ]; + type __ = Exclude, HasTagName>; +} + +{ + type _ = [ + __Expect>, + __Expect, HasIsTypeOnly>, + ]; + type __ = Exclude, HasIsTypeOnly>; +} + // Registry /** @@ -619,4 +823,4 @@ export interface NodeMap { */ export type Nodes = NodeMap[keyof NodeMap]; -type __Expect = never; // eslint-disable-line @typescript-eslint/naming-convention +type __Expect = never; diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index 959c97890c0..47c90807da7 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -35,6 +35,7 @@ import { AstConciseBody, AstConstructorDeclaration, AstConstructSignatureDeclaration, + astContainsParseError, AstDecorator, AstDefaultClause, AstDoStatement, @@ -58,6 +59,9 @@ import { AstFunctionDeclaration, AstFunctionExpression, AstFunctionOrConstructorTypeNode, + astGetFullWidth, + astGetModifiers, + astGetTextOfNodeFromSourceText, AstHasJSDoc, astHasJSDoc, astHasJSDocNodes, @@ -75,6 +79,32 @@ import { AstIndexSignatureDeclaration, AstInferTypeNode, AstInterfaceDeclaration, + astIsAsyncModifier, + astIsDeclareKeyword, + astIsExportAssignment, + astIsExportDeclaration, + astIsExportModifier, + astIsExpressionWithTypeArguments, + astIsExternalModuleReference, + astIsFunctionTypeNode, + astIsIdentifier, + astIsImportDeclaration, + astIsImportEqualsDeclaration, + astIsJSDocFunctionType, + astIsJSDocNullableType, + astIsJSDocReturnTag, + astIsJSDocTypeTag, + astIsJsxNamespacedName, + astIsJsxOpeningElement, + astIsJsxOpeningFragment, + astIsLeftHandSideExpression, + astIsMetaProperty, + astIsNonNullExpression, + astIsPrivateIdentifier, + astIsSetAccessorDeclaration, + astIsStringOrNumericLiteralLike, + astIsTaggedTemplateExpression, + astIsTypeReferenceNode, AstIterationStatement, AstJSDoc, AstJSDocAllType, @@ -145,6 +175,7 @@ import { AstMissingDeclaration, AstModifier, AstModifierLike, + astModifiersToFlags, AstModuleBlock, AstModuleDeclaration, AstModuleExportName, @@ -159,6 +190,8 @@ import { AstNode, AstNodeArray, AstNodeArrayLike, + astNodeIsMissing, + astNodeIsPresent, AstNoSubstitutionTemplateLiteral, AstNullLiteral, AstNumericLiteral, @@ -230,7 +263,6 @@ import { commentPragmas, CommentRange, concatenate, - containsParseError, convertToJson, createAstNodeFactory, createDetachedDiagnostic, @@ -256,42 +288,14 @@ import { getAnyExtensionFromPath, getBaseFileName, getBinaryOperatorPrecedence, - getFullWidth, getJSDocCommentRanges, getLanguageVariant, getLastChild, getLeadingCommentRanges, getSpellingSuggestion, - getTextOfNodeFromSourceText, identity, isArray, isAssignmentOperator, - isAstAsyncModifier, - isAstDeclareKeyword, - isAstExportAssignment, - isAstExportDeclaration, - isAstExportModifier, - isAstExpressionWithTypeArguments, - isAstExternalModuleReference, - isAstFunctionTypeNode, - isAstIdentifier, - isAstImportDeclaration, - isAstImportEqualsDeclaration, - isAstJSDocFunctionType, - isAstJSDocNullableType, - isAstJSDocReturnTag, - isAstJSDocTypeTag, - isAstJsxNamespacedName, - isAstJsxOpeningElement, - isAstJsxOpeningFragment, - isAstLeftHandSideExpression, - isAstMetaProperty, - isAstNonNullExpression, - isAstPrivateIdentifier, - isAstSetAccessorDeclaration, - isAstStringOrNumericLiteralLike, - isAstTaggedTemplateExpression, - isAstTypeReferenceNode, isClassMemberModifier, isIdentifierText, isKeyword, @@ -311,15 +315,12 @@ import { map, mapDefined, ModifierFlags, - modifiersToFlags, ModuleKind, Mutable, Node, NodeFactory, NodeFactoryFlags, NodeFlags, - nodeIsMissing, - nodeIsPresent, noop, normalizePath, OperatorPrecedence, @@ -406,10 +407,10 @@ export function isFileProbablyExternalModule(sourceFile: SourceFile): Node | und function isAnExternalModuleIndicatorNode(node: AstNode) { return astCanHaveModifiers(node) && hasModifierOfKind(node, SyntaxKind.ExportKeyword) - || isAstImportEqualsDeclaration(node) && isAstExternalModuleReference(node.data.moduleReference) - || isAstImportDeclaration(node) - || isAstExportAssignment(node) - || isAstExportDeclaration(node) ? node : undefined; + || astIsImportEqualsDeclaration(node) && astIsExternalModuleReference(node.data.moduleReference) + || astIsImportDeclaration(node) + || astIsExportAssignment(node) + || astIsExportDeclaration(node) ? node : undefined; } function getImportMetaIfNecessary(sourceFile: SourceFile) { @@ -424,11 +425,11 @@ function walkTreeForImportMeta(node: AstNode): AstNode | undefined { /** Do not use hasModifier inside the parser; it relies on parent pointers. Use this instead. */ function hasModifierOfKind(node: AstHasModifiers, kind: SyntaxKind) { - return some(node.data.modifiers?.items, m => m.kind === kind); + return some(astGetModifiers(node)?.items, m => m.kind === kind); } function isImportMeta(node: AstNode): boolean { - return isAstMetaProperty(node) && node.data.keywordToken === SyntaxKind.ImportKeyword && node.data.name.data.escapedText === "meta"; + return astIsMetaProperty(node) && node.data.keywordToken === SyntaxKind.ImportKeyword && node.data.name.data.escapedText === "meta"; } export interface CreateSourceFileOptions { @@ -497,7 +498,13 @@ export function parseJsonText(fileName: string, sourceText: string): JsonSourceF // See also `isExternalOrCommonJsModule` in utilities.ts export function isExternalModule(file: SourceFile): boolean { - return file.externalModuleIndicator !== undefined; + return astIsExternalModule(file.ast); +} + +// See also `isExternalOrCommonJsModule` in utilities.ts +/** @internal */ +export function astIsExternalModule(file: AstSourceFile): boolean { + return file.data.externalModuleIndicator !== undefined; } // Produces a new SourceFile for the 'newText' provided. The 'textChangeRange' parameter @@ -1456,13 +1463,13 @@ namespace Parser { // Tagged template literals are sometimes used in places where only simple strings are allowed, i.e.: // module `M1` { // ^^^^^^^^^^^ This block is parsed as a template literal like module`M1`. - if (isAstTaggedTemplateExpression(node)) { + if (astIsTaggedTemplateExpression(node)) { parseErrorAt(skipTrivia(sourceText, node.data.template.pos), node.data.template.end, Diagnostics.Module_declaration_names_may_only_use_or_quoted_strings); return; } // Otherwise, if this isn't a well-known keyword-like identifier, give the generic fallback message. - const expressionText = isAstIdentifier(node) ? unescapeLeadingUnderscores(node.data.escapedText) : undefined; + const expressionText = astIsIdentifier(node) ? unescapeLeadingUnderscores(node.data.escapedText) : undefined; if (!expressionText || !isIdentifierText(expressionText, languageVersion)) { parseErrorAtCurrentToken(Diagnostics._0_expected, tokenToString(SyntaxKind.SemicolonToken)); return; @@ -2226,7 +2233,7 @@ namespace Parser { // Can't reuse a node that intersected the change range. // Can't reuse a node that contains a parse error. This is necessary so that we // produce the same set of errors again. - if (nodeIsMissing(node) || intersectsIncrementalChange(node) || containsParseError(node)) { + if (astNodeIsMissing(node) || intersectsIncrementalChange(node) || astContainsParseError(node)) { return undefined; } @@ -2898,7 +2905,7 @@ namespace Parser { function typeHasArrowFunctionBlockingParseError(node: AstTypeNode): boolean { switch (node.kind) { case SyntaxKind.TypeReference: - return nodeIsMissing((node as AstTypeReferenceNode).data.typeName); + return astNodeIsMissing((node as AstTypeReferenceNode).data.typeName); case SyntaxKind.FunctionType: case SyntaxKind.ConstructorType: { const { data: { parameters, type } } = node as AstFunctionOrConstructorTypeNode; @@ -3091,7 +3098,7 @@ namespace Parser { // FormalParameter [Yield,Await]: // BindingElement[?Yield,?Await] const name = parseIdentifierOrPattern(Diagnostics.Private_identifiers_cannot_be_used_as_parameters); - if (getFullWidth(name) === 0 && !some(modifiers?.items) && isModifierKind(token())) { + if (astGetFullWidth(name) === 0 && !some(modifiers?.items) && isModifierKind(token())) { // in cases like // 'use strict' // function foo(static) @@ -3532,7 +3539,7 @@ namespace Parser { return finishNode(factory.createRestTypeNode(parseType()), pos); } const type = parseType(); - if (isAstJSDocNullableType(type) && type.pos === type.data.type.pos) { + if (astIsJSDocNullableType(type) && type.pos === type.data.type.pos) { const node = factory.createOptionalTypeNode(type.data.type); setTextRange(node, type); node.flags = type.flags; @@ -3890,7 +3897,7 @@ namespace Parser { if (isStartOfFunctionTypeOrConstructorType()) { const type = parseFunctionOrConstructorType(); let diagnostic: DiagnosticMessage; - if (isAstFunctionTypeNode(type)) { + if (astIsFunctionTypeNode(type)) { diagnostic = isInUnionType ? Diagnostics.Function_type_notation_must_be_parenthesized_when_used_in_a_union_type : Diagnostics.Function_type_notation_must_be_parenthesized_when_used_in_an_intersection_type; @@ -4215,7 +4222,7 @@ namespace Parser { // // Note: we call reScanGreaterToken so that we get an appropriately merged token // for cases like `> > =` becoming `>>=` - if (isAstLeftHandSideExpression(expr) && isAssignmentOperator(reScanGreaterToken())) { + if (astIsLeftHandSideExpression(expr) && isAssignmentOperator(reScanGreaterToken())) { return makeBinaryExpression(expr, parseTokenNode(), parseAssignmentExpressionOrHigher(allowReturnTypeInArrowFunction), pos); } @@ -4521,7 +4528,7 @@ namespace Parser { const pos = getNodePos(); const hasJSDoc = hasPrecedingJSDocComment(); const modifiers = parseModifiersForArrowFunction(); - const isAsync = some(modifiers?.items, isAstAsyncModifier) ? SignatureFlags.Await : SignatureFlags.None; + const isAsync = some(modifiers?.items, astIsAsyncModifier) ? SignatureFlags.Await : SignatureFlags.None; // Arrow functions are never generators. // // If we're speculatively parsing a signature for a parenthesized arrow function, then @@ -4576,7 +4583,7 @@ namespace Parser { unwrappedType = (unwrappedType as AstParenthesizedTypeNode).data.type; // Skip parens if need be } - const hasJSDocFunctionType = unwrappedType && isAstJSDocFunctionType(unwrappedType); + const hasJSDocFunctionType = unwrappedType && astIsJSDocFunctionType(unwrappedType); if (!allowAmbiguity && token() !== SyntaxKind.EqualsGreaterThanToken && (hasJSDocFunctionType || token() !== SyntaxKind.OpenBraceToken)) { // Returning undefined here will cause our caller to rewind to where we started from. return undefined; @@ -4587,7 +4594,7 @@ namespace Parser { const lastToken = token(); const equalsGreaterThanToken = parseExpectedToken(SyntaxKind.EqualsGreaterThanToken); const body = (lastToken === SyntaxKind.EqualsGreaterThanToken || lastToken === SyntaxKind.OpenBraceToken) - ? parseArrowFunctionExpressionBody(some(modifiers?.items, isAstAsyncModifier), allowReturnTypeInArrowFunction) + ? parseArrowFunctionExpressionBody(some(modifiers?.items, astIsAsyncModifier), allowReturnTypeInArrowFunction) : parseIdentifier(); // Given: @@ -4674,7 +4681,7 @@ namespace Parser { questionToken, doOutsideOfContext(disallowInAndDecoratorContext, () => parseAssignmentExpressionOrHigher(/*allowReturnTypeInArrowFunction*/ false)), colonToken = parseExpectedToken(SyntaxKind.ColonToken), - nodeIsPresent(colonToken) + astNodeIsPresent(colonToken) ? parseAssignmentExpressionOrHigher(allowReturnTypeInArrowFunction) : createMissingNode(SyntaxKind.Identifier, /*reportAtCurrentPosition*/ false, Diagnostics._0_expected, tokenToString(SyntaxKind.ColonToken)), ), @@ -4971,7 +4978,7 @@ namespace Parser { const expression = parseLeftHandSideExpressionOrHigher(); - Debug.assert(isAstLeftHandSideExpression(expression)); + Debug.assert(astIsLeftHandSideExpression(expression)); if ((token() === SyntaxKind.PlusPlusToken || token() === SyntaxKind.MinusMinusToken) && !scanner.hasPrecedingLineBreak()) { const operator = token() as PostfixUnaryOperator; nextToken(); @@ -5158,13 +5165,13 @@ namespace Parser { else { closingElement = parseJsxClosingElement(opening, inExpressionContext); if (!tagNamesAreEquivalent(opening.data.tagName, closingElement.data.tagName)) { - if (openingTag && isAstJsxOpeningElement(openingTag) && tagNamesAreEquivalent(closingElement.data.tagName, openingTag.data.tagName)) { + if (openingTag && astIsJsxOpeningElement(openingTag) && tagNamesAreEquivalent(closingElement.data.tagName, openingTag.data.tagName)) { // opening incorrectly matched with its parent's closing -- put error on opening - parseErrorAtRange(opening.data.tagName, Diagnostics.JSX_element_0_has_no_corresponding_closing_tag, getTextOfNodeFromSourceText(sourceText, opening.data.tagName)); + parseErrorAtRange(opening.data.tagName, Diagnostics.JSX_element_0_has_no_corresponding_closing_tag, astGetTextOfNodeFromSourceText(sourceText, opening.data.tagName)); } else { // other opening/closing mismatches -- put error on closing - parseErrorAtRange(closingElement.data.tagName, Diagnostics.Expected_corresponding_JSX_closing_tag_for_0, getTextOfNodeFromSourceText(sourceText, opening.data.tagName)); + parseErrorAtRange(closingElement.data.tagName, Diagnostics.Expected_corresponding_JSX_closing_tag_for_0, astGetTextOfNodeFromSourceText(sourceText, opening.data.tagName)); } } } @@ -5215,7 +5222,7 @@ namespace Parser { case SyntaxKind.EndOfFileToken: // If we hit EOF, issue the error at the tag that lacks the closing element // rather than at the end of the file (which is useless) - if (isAstJsxOpeningFragment(openingTag)) { + if (astIsJsxOpeningFragment(openingTag)) { parseErrorAtRange(openingTag, Diagnostics.JSX_fragment_has_no_corresponding_closing_tag); } else { @@ -5223,7 +5230,7 @@ namespace Parser { // or to cover only 'Foo' in < Foo > const tag = openingTag.data.tagName; const start = Math.min(skipTrivia(sourceText, tag.pos), tag.end); - parseErrorAt(start, tag.end, Diagnostics.JSX_element_0_has_no_corresponding_closing_tag, getTextOfNodeFromSourceText(sourceText, openingTag.data.tagName)); + parseErrorAt(start, tag.end, Diagnostics.JSX_element_0_has_no_corresponding_closing_tag, astGetTextOfNodeFromSourceText(sourceText, openingTag.data.tagName)); } return undefined; case SyntaxKind.LessThanSlashToken: @@ -5252,7 +5259,7 @@ namespace Parser { if (!child) break; list.push(child); if ( - isAstJsxOpeningElement(openingTag) + astIsJsxOpeningElement(openingTag) && child?.kind === SyntaxKind.JsxElement && !tagNamesAreEquivalent(child.data.openingElement.data.tagName, child.data.closingElement.data.tagName) && tagNamesAreEquivalent(openingTag.data.tagName, child.data.closingElement.data.tagName) @@ -5319,7 +5326,7 @@ namespace Parser { // We can't just simply use parseLeftHandSideExpressionOrHigher because then we will start consider class,function etc as a keyword // We only want to consider "this" as a primaryExpression const initialExpression = parseJsxTagName(); - if (isAstJsxNamespacedName(initialExpression)) { + if (astIsJsxNamespacedName(initialExpression)) { return initialExpression; // `a:b.c` is invalid syntax, don't even look for the `.` if we parse `a:b`, and let `parseAttribute` report "unexpected :" instead. } let expression: AstPropertyAccessExpression | AstIdentifier | AstThisExpression = initialExpression; @@ -5475,14 +5482,14 @@ namespace Parser { return true; } // check for an optional chain in a non-null expression - if (isAstNonNullExpression(node)) { + if (astIsNonNullExpression(node)) { let expr = node.data.expression; - while (isAstNonNullExpression(expr) && !(expr.flags & NodeFlags.OptionalChain)) { + while (astIsNonNullExpression(expr) && !(expr.flags & NodeFlags.OptionalChain)) { expr = expr.data.expression; } if (expr.flags & NodeFlags.OptionalChain) { // this is part of an optional chain. Walk down from `node` to `expression` and set the flag. - while (isAstNonNullExpression(node)) { + while (astIsNonNullExpression(node)) { node.flags |= NodeFlags.OptionalChain; node = node.data.expression; } @@ -5498,10 +5505,10 @@ namespace Parser { const propertyAccess = isOptionalChain ? factoryCreatePropertyAccessChain(expression, questionDotToken, name) : factoryCreatePropertyAccessExpression(expression, name); - if (isOptionalChain && isAstPrivateIdentifier(propertyAccess.data.name)) { + if (isOptionalChain && astIsPrivateIdentifier(propertyAccess.data.name)) { parseErrorAtRange(propertyAccess.data.name, Diagnostics.An_optional_chain_cannot_contain_private_identifiers); } - if (isAstExpressionWithTypeArguments(expression) && expression.data.typeArguments) { + if (astIsExpressionWithTypeArguments(expression) && expression.data.typeArguments) { const pos = expression.data.typeArguments.pos - 1; const end = skipTrivia(sourceText, expression.data.typeArguments.end) + 1; parseErrorAt(pos, end, Diagnostics.An_instantiation_expression_cannot_be_followed_by_a_property_access); @@ -5516,7 +5523,7 @@ namespace Parser { } else { const argument = allowInAnd(parseExpression); - if (isAstStringOrNumericLiteralLike(argument)) { + if (astIsStringOrNumericLiteralLike(argument)) { argument.data.text = internIdentifier(argument.data.text); } argumentExpression = argument; @@ -5555,7 +5562,7 @@ namespace Parser { if (isTemplateStartOfTaggedTemplate()) { // Absorb type arguments into TemplateExpression when preceding expression is ExpressionWithTypeArguments - expression = !questionDotToken && isAstExpressionWithTypeArguments(expression) ? + expression = !questionDotToken && astIsExpressionWithTypeArguments(expression) ? parseTaggedTemplateRest(pos, expression.data.expression, questionDotToken, expression.data.typeArguments) : parseTaggedTemplateRest(pos, expression, questionDotToken, /*typeArguments*/ undefined); continue; @@ -5611,7 +5618,7 @@ namespace Parser { } if (typeArguments || token() === SyntaxKind.OpenParenToken) { // Absorb type arguments into CallExpression when preceding expression is ExpressionWithTypeArguments - if (!questionDotToken && isAstExpressionWithTypeArguments(expression)) { + if (!questionDotToken && astIsExpressionWithTypeArguments(expression)) { typeArguments = expression.data.typeArguments; expression = expression.data.expression; } @@ -5857,7 +5864,7 @@ namespace Parser { parseExpected(SyntaxKind.FunctionKeyword); const asteriskToken = parseOptionalToken(SyntaxKind.AsteriskToken); const isGenerator = asteriskToken ? SignatureFlags.Yield : SignatureFlags.None; - const isAsync = some(modifiers?.items, isAstAsyncModifier) ? SignatureFlags.Await : SignatureFlags.None; + const isAsync = some(modifiers?.items, astIsAsyncModifier) ? SignatureFlags.Await : SignatureFlags.None; const name = isGenerator && isAsync ? doInYieldAndAwaitContext(parseOptionalBindingIdentifier) : isGenerator ? doInYieldContext(parseOptionalBindingIdentifier) : isAsync ? doInAwaitContext(parseOptionalBindingIdentifier) : @@ -5889,12 +5896,12 @@ namespace Parser { let expression: AstLeftHandSideExpression = parseMemberExpressionRest(expressionPos, parsePrimaryExpression(), /*allowOptionalChain*/ false); let typeArguments: AstNodeArray | undefined; // Absorb type arguments into NewExpression when preceding expression is ExpressionWithTypeArguments - if (isAstExpressionWithTypeArguments(expression)) { + if (astIsExpressionWithTypeArguments(expression)) { typeArguments = expression.data.typeArguments; expression = expression.data.expression; } if (token() === SyntaxKind.QuestionDotToken) { - parseErrorAtCurrentToken(Diagnostics.Invalid_optional_chain_from_new_expression_Did_you_mean_to_call_0, getTextOfNodeFromSourceText(sourceText, expression)); + parseErrorAtCurrentToken(Diagnostics.Invalid_optional_chain_from_new_expression_Did_you_mean_to_call_0, astGetTextOfNodeFromSourceText(sourceText, expression)); } const argumentList = token() === SyntaxKind.OpenParenToken ? parseArgumentList() : undefined; return finishNode(factoryCreateNewExpression(expression, typeArguments, argumentList), pos); @@ -6209,7 +6216,7 @@ namespace Parser { let node: AstExpressionStatement | AstLabeledStatement; const hasParen = token() === SyntaxKind.OpenParenToken; const expression = allowInAnd(parseExpression); - if (isAstIdentifier(expression) && parseOptional(SyntaxKind.ColonToken)) { + if (astIsIdentifier(expression) && parseOptional(SyntaxKind.ColonToken)) { node = factory.createLabeledStatement(expression, parseStatement()); } else { @@ -6538,7 +6545,7 @@ namespace Parser { const pos = getNodePos(); const hasJSDoc = hasPrecedingJSDocComment(); const modifiers = parseModifiers(/*allowDecorators*/ true); - const isAmbient = some(modifiers?.items, isAstDeclareKeyword); + const isAmbient = some(modifiers?.items, astIsDeclareKeyword); if (isAmbient) { const node = tryReuseAmbientDeclaration(pos); if (node) { @@ -6795,7 +6802,7 @@ namespace Parser { function parseFunctionDeclaration(pos: number, hasJSDoc: boolean, modifiers: AstNodeArray | undefined): AstFunctionDeclaration { const savedAwaitContext = inAwaitContext(); - const modifierFlags = modifiersToFlags(modifiers?.items); + const modifierFlags = astModifiersToFlags(modifiers?.items); parseExpected(SyntaxKind.FunctionKeyword); const asteriskToken = parseOptionalToken(SyntaxKind.AsteriskToken); // We don't parse the name here in await context, instead we will report a grammar error in the checker. @@ -6852,7 +6859,7 @@ namespace Parser { diagnosticMessage?: DiagnosticMessage, ): AstMethodDeclaration { const isGenerator = asteriskToken ? SignatureFlags.Yield : SignatureFlags.None; - const isAsync = some(modifiers?.items, isAstAsyncModifier) ? SignatureFlags.Await : SignatureFlags.None; + const isAsync = some(modifiers?.items, astIsAsyncModifier) ? SignatureFlags.Await : SignatureFlags.None; const typeParameters = parseTypeParameters(); const parameters = parseParameters(isGenerator | isAsync); const type = parseReturnType(SyntaxKind.ColonToken, /*isType*/ false); @@ -6921,7 +6928,7 @@ namespace Parser { : factory.createSetAccessorDeclaration(modifiers, name, parameters, body); // Keep track of `typeParameters` (for both) and `type` (for setters) if they were parsed those indicate grammar errors node.data.typeParameters = typeParameters; - if (isAstSetAccessorDeclaration(node)) { + if (astIsSetAccessorDeclaration(node)) { node.data.type = type; } return withJSDoc(finishNode(node, pos), hasJSDoc); @@ -7171,7 +7178,7 @@ namespace Parser { token() === SyntaxKind.AsteriskToken || token() === SyntaxKind.OpenBracketToken ) { - const isAmbient = some(modifiers?.items, isAstDeclareKeyword); + const isAmbient = some(modifiers?.items, astIsDeclareKeyword); if (isAmbient) { for (const m of modifiers!.items) { m.flags |= NodeFlags.Ambient; @@ -7222,7 +7229,7 @@ namespace Parser { // We don't parse the name here in await context, instead we will report a grammar error in the checker. const name = parseNameOfClassDeclarationOrExpression(); const typeParameters = parseTypeParameters(); - if (some(modifiers?.items, isAstExportModifier)) setAwaitContext(/*value*/ true); + if (some(modifiers?.items, astIsExportModifier)) setAwaitContext(/*value*/ true); const heritageClauses = parseHeritageClauses(); let members; @@ -8466,7 +8473,7 @@ namespace Parser { case SyntaxKind.ArrayType: return isObjectOrObjectArrayTypeReference((node as AstArrayTypeNode).data.elementType); default: - return isAstTypeReferenceNode(node) && isAstIdentifier(node.data.typeName) && node.data.typeName.data.escapedText === "Object" && !node.data.typeArguments; + return astIsTypeReferenceNode(node) && astIsIdentifier(node.data.typeName) && node.data.typeName.data.escapedText === "Object" && !node.data.typeArguments; } } @@ -8516,7 +8523,7 @@ namespace Parser { } function parseReturnTag(start: number, tagName: AstIdentifier, indent: number, indentText: string): AstJSDocReturnTag { - if (some(tags, isAstJSDocReturnTag)) { + if (some(tags, astIsJSDocReturnTag)) { parseErrorAt(tagName.pos, scanner.getTokenStart(), Diagnostics._0_tag_already_specified, unescapeLeadingUnderscores(tagName.data.escapedText)); } @@ -8525,7 +8532,7 @@ namespace Parser { } function parseTypeTag(start: number, tagName: AstIdentifier, indent?: number, indentText?: string): AstJSDocTypeTag { - if (some(tags, isAstJSDocTypeTag)) { + if (some(tags, astIsJSDocTypeTag)) { parseErrorAt(tagName.pos, scanner.getTokenStart(), Diagnostics._0_tag_already_specified, unescapeLeadingUnderscores(tagName.data.escapedText)); } @@ -8790,8 +8797,8 @@ namespace Parser { } function escapedTextsEqual(a: AstEntityName, b: AstEntityName): boolean { - while (!isAstIdentifier(a) || !isAstIdentifier(b)) { - if (!isAstIdentifier(a) && !isAstIdentifier(b) && a.data.right.data.escapedText === b.data.right.data.escapedText) { + while (!astIsIdentifier(a) || !astIsIdentifier(b)) { + if (!astIsIdentifier(a) && !astIsIdentifier(b) && a.data.right.data.escapedText === b.data.right.data.escapedText) { a = a.data.left; b = b.data.left; } @@ -8816,7 +8823,7 @@ namespace Parser { const child = tryParseChildTag(target, indent); if ( child && (child.kind === SyntaxKind.JSDocParameterTag || child.kind === SyntaxKind.JSDocPropertyTag) && - name && (isAstIdentifier(child.data.name) || !escapedTextsEqual(name, child.data.name.data.left)) + name && (astIsIdentifier(child.data.name) || !escapedTextsEqual(name, child.data.name.data.left)) ) { return false; } @@ -8893,7 +8900,7 @@ namespace Parser { parseExpected(SyntaxKind.CloseBracketToken); } - if (nodeIsMissing(name)) { + if (astNodeIsMissing(name)) { return undefined; } return finishNode(factory.createTypeParameterDeclaration(modifiers, name, /*constraint*/ undefined, defaultType), typeParameterPos); @@ -9415,7 +9422,7 @@ namespace IncrementalParser { } function visit(child: AstNode) { - if (nodeIsMissing(child)) { + if (astNodeIsMissing(child)) { // Missing nodes are effectively invisible to us. We never even consider them // When trying to find the nearest node before us. return; diff --git a/src/compiler/readonlyArray.ts b/src/compiler/readonlyArray.ts new file mode 100644 index 00000000000..4080fde9422 --- /dev/null +++ b/src/compiler/readonlyArray.ts @@ -0,0 +1,116 @@ +function canonicalNumericIndexString(argument: string) { + if (argument === "-0") { + return -0; + } + const n = Number(argument); + if (String(n) === argument) { + return n; + } + return undefined; +} + +function isValidIntegerIndex(argument: string | symbol) { + if (typeof argument === "string") { + const index = canonicalNumericIndexString(argument); + if (index !== undefined && Number.isInteger(index)) { + return true; + } + } + return false; +} + +const readonlyArrayViewBrand = new WeakSet(); +const readonlyArrayViewData = new WeakMap any}>(); +const readonlyArrayViewHandler: ProxyHandler = { + defineProperty(o, p, desc) { + if (p === "length" || isValidIntegerIndex(p)) { + const { source, mapper } = readonlyArrayViewData.get(o)!; + const existing = Reflect.getOwnPropertyDescriptor(source, p); + if (!existing) { + return false; + } + if (p !== "length") { + existing.value = mapper(existing.value); + } + return existing.get === desc.get && + existing.set === desc.set && + existing.configurable === desc.configurable && + existing.enumerable === desc.enumerable && + existing.writable === desc.writable && + existing.value === desc.value; + } + return Reflect.defineProperty(o, p, desc); + }, + getOwnPropertyDescriptor(o, p) { + const { source, mapper } = readonlyArrayViewData.get(o)!; + if (p === "length") { + return Reflect.getOwnPropertyDescriptor(source, p); + } + if (isValidIntegerIndex(p)) { + const existing = Reflect.getOwnPropertyDescriptor(source, p); + if (existing?.value !== undefined) { + existing.value = mapper(existing.value); + } + return existing; + } + return Reflect.getOwnPropertyDescriptor(o, p); + }, + has(o, p) { + const { source } = readonlyArrayViewData.get(o)!; + if (p === "length" || isValidIntegerIndex(p)) { + return Reflect.has(source, p); + } + return Reflect.has(o, p); + }, + get(o, p, receiver) { + const { source, mapper } = readonlyArrayViewData.get(o)!; + if (p === "length") { + return Reflect.get(source, p, receiver); + } + if (isValidIntegerIndex(p)) { + const value = Reflect.get(source, p, receiver); + return value !== undefined ? mapper(value) : value; + } + return Reflect.get(o, p, receiver); + }, + set(o, p, v, receiver) { + if (p === "length" || isValidIntegerIndex(p)) { + return false; + } + return Reflect.set(o, p, v, receiver); + }, + deleteProperty(o, p) { + if (p === "length" || isValidIntegerIndex(p)) { + return false; + } + return Reflect.deleteProperty(o, p); + }, + preventExtensions(_o) { + return false; + }, +}; + +/** @internal */ +export interface ReadonlyArrayView extends ReadonlyArray { + _readonlyArrayViewBrand: any; +} + +/** @internal */ +export interface ReadonlyArrayViewConstructor { + new (source: readonly T[], mapper: (value: T) => U): ReadonlyArrayView; + isReadonlyArrayView(obj: unknown): obj is ReadonlyArrayView; +} + +/** @internal */ +// eslint-disable-next-line local/only-arrow-functions +export const ReadonlyArrayView = function (source: readonly T[], mapper: (value: T) => U) { + const array: readonly U[] = []; + const proxy = new Proxy(array, readonlyArrayViewHandler); + readonlyArrayViewData.set(array, { source, mapper }); + readonlyArrayViewBrand.add(proxy); + return proxy; +} as unknown as ReadonlyArrayViewConstructor; + +ReadonlyArrayView.isReadonlyArrayView = (obj): obj is ReadonlyArrayView => { + return typeof obj === "object" && !!obj && readonlyArrayViewBrand.has(obj); +}; diff --git a/src/compiler/tsconfig.json b/src/compiler/tsconfig.json index cbbd3df0beb..cfb7213a17e 100644 --- a/src/compiler/tsconfig.json +++ b/src/compiler/tsconfig.json @@ -1,7 +1,8 @@ { "extends": "../tsconfig-base", "compilerOptions": { - "types": ["node"] + "types": ["node"], + "experimentalDecorators": true }, "references": [], diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 34d36d5714d..4ab24b73c67 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -209,7 +209,7 @@ import { AstTryStatementData, AstTupleTypeNodeData, AstTypeAliasDeclarationData, - AstTypeAssertionData, + AstTypeAssertionExpressionData, AstTypeLiteralNodeData, AstTypeOfExpressionData, AstTypeOperatorNodeData, @@ -315,6 +315,24 @@ import { AstEntityNameExpression, AstQuestionDotToken, AstMemberName, + AstStringLiteralLike, + AstNumericLiteral, + AstObjectLiteralExpression, + AstBindableStaticNameExpression, + AstWrappedExpression, + AstNodeOneOf, + AstLeftHandSideExpression, + AstBindableStaticAccessExpression, + AstEntityName, + AstJSDocTypeExpression, + AstComputedPropertyName, + AstElementAccessExpression, + AstDeclaration, + AstModuleBlock, + AstStringLiteral, + astGetComment, + astSetComment, + AstJSDocUnknownTag, } from "./_namespaces/ts.js"; // branded string type used to store absolute, normalized and canonicalized paths @@ -1254,12 +1272,12 @@ export class Node< get pos(): number { return this.ast.pos; } get end(): number { return this.ast.end; } get flags(): NodeFlags { return this.ast.flags; } - get parent(): Node { return this.ast.parent?.node!; } + get parent(): Node { return this.ast.parent?.node; } /** @internal */ set pos(value) { this.ast.pos = value; } /** @internal */ set end(value) { this.ast.end = value; } /** @internal */ set flags(value) { this.ast.flags = value; } - /** @internal */ set parent(value) { this.ast.parent = value?.ast; } + /** @internal */ set parent(value) { this.ast.parent = value?.ast as typeof this.ast.parent; } /** @internal */ get modifierFlagsCache(): ModifierFlags { return this.ast.modifierFlagsCache; } /** @internal */ set modifierFlagsCache(value) { this.ast.modifierFlagsCache = value; } /** @internal */ get transformFlags(): TransformFlags { return this.ast.transformFlags; } @@ -1520,11 +1538,22 @@ export type HasFlowNode = | TryStatement | DebuggerStatement; +/** @internal */ +export type HasEndFlowNode = + | MethodDeclaration + | ClassStaticBlockDeclaration + | ConstructorDeclaration + | GetAccessorDeclaration + | SetAccessorDeclaration + | FunctionExpression + | ArrowFunction + | FunctionDeclaration + | SourceFile; + // 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, // but are constructed as if they could for faked-up `QualifiedName`s in the language service.) - /** @internal */ export type ForEachChildNodes = | HasChildren @@ -1794,7 +1823,20 @@ export type HasType = | JSDocNonNullableType | JSDocNullableType | JSDocOptionalType - | JSDocVariadicType; + | JSDocVariadicType + | OptionalTypeNode + | RestTypeNode + | NamedTupleMember + | TemplateLiteralTypeSpan + | SatisfiesExpression + | JSDocNamepathType + | JSDocSignature; + +/** @internal */ +export type HasTypes = + | UnionTypeNode + | IntersectionTypeNode + | HeritageClause; // NOTE: Changing the following list requires changes to: // - `canHaveIllegalType` in factory/utilities.ts @@ -1803,6 +1845,29 @@ export type HasIllegalType = | ConstructorDeclaration | SetAccessorDeclaration; +/** @internal */ +export type HasTypeParameters = + | ConstructorDeclaration + | SetAccessorDeclaration + | GetAccessorDeclaration + | CallSignatureDeclaration + | ConstructSignatureDeclaration + | MethodSignature + | IndexSignatureDeclaration + | MethodDeclaration + | FunctionDeclaration + | JSDocSignature + | JSDocFunctionType + | FunctionTypeNode + | ConstructorTypeNode + | FunctionExpression + | ArrowFunction + | ClassExpression + | ClassDeclaration + | InterfaceDeclaration + | TypeAliasDeclaration + | JSDocTemplateTag; + // NOTE: Changing the following list requires changes to: // - `canHaveIllegalTypeParameters` in factory/utilities.ts /** @internal */ @@ -1811,13 +1876,186 @@ export type HasIllegalTypeParameters = | SetAccessorDeclaration | GetAccessorDeclaration; +/** @internal */ +export type HasParameters = + | ConstructorDeclaration + | SetAccessorDeclaration + | GetAccessorDeclaration + | CallSignatureDeclaration + | ConstructSignatureDeclaration + | MethodSignature + | IndexSignatureDeclaration + | MethodDeclaration + | FunctionDeclaration + | JSDocSignature + | JSDocFunctionType + | FunctionTypeNode + | ConstructorTypeNode + | FunctionExpression + | ArrowFunction; + +/** @internal */ +export type HasBody = + | MethodDeclaration + | ClassStaticBlockDeclaration + | ConstructorDeclaration + | GetAccessorDeclaration + | SetAccessorDeclaration + | FunctionDeclaration + | FunctionExpression + | ArrowFunction + | ModuleDeclaration; + export type HasTypeArguments = | CallExpression | NewExpression | TaggedTemplateExpression + | ExpressionWithTypeArguments + | TypeQueryNode + | ImportTypeNode + | TypeReferenceNode | JsxOpeningElement | JsxSelfClosingElement; +/** @internal */ +export type InternalHasTypeArguments = + | HasTypeArguments + | MethodSignature + | MethodDeclaration + | ConstructorDeclaration + | GetAccessorDeclaration + | SetAccessorDeclaration + | CallSignatureDeclaration + | ConstructSignatureDeclaration + | IndexSignatureDeclaration + | FunctionTypeNode + | ConstructorTypeNode + | FunctionExpression + | ArrowFunction + | FunctionDeclaration + | JSDocFunctionType; + +/** @internal */ +export type HasElements = + | TupleTypeNode + | ObjectBindingPattern + | ArrayBindingPattern + | ArrayLiteralExpression + | ImportAttributes + | NamedImports + | NamedExports + | CommaListExpression; + +/** @internal */ +export type HasMembers = + | TypeLiteralNode + | MappedTypeNode + | ClassExpression + | ClassDeclaration + | InterfaceDeclaration + | EnumDeclaration; + +/** @internal */ +export type HasStatement = + | DoStatement + | WhileStatement + | ForStatement + | ForInStatement + | ForOfStatement + | WithStatement + | LabeledStatement; + +/** @internal */ +export type HasStatements = + | Block + | ModuleBlock + | CaseClause + | DefaultClause + | SourceFile; + +/** @internal */ +export type HasExclamationToken = + | MethodDeclaration + | PropertyAssignment + | PropertyDeclaration + | ShorthandPropertyAssignment + | VariableDeclaration; + +/** @internal */ +export type HasQuestionDotToken = + | PropertyAccessExpression + | ElementAccessExpression + | CallExpression + | TaggedTemplateExpression; + +/** @internal */ +export type HasTagName = + | JsxSelfClosingElement + | JsxOpeningElement + | JsxClosingElement + | JSDocUnknownTag + | JSDocAugmentsTag + | JSDocImplementsTag + | JSDocAuthorTag + | JSDocDeprecatedTag + | JSDocClassTag + | JSDocPublicTag + | JSDocPrivateTag + | JSDocProtectedTag + | JSDocReadonlyTag + | JSDocOverrideTag + | JSDocCallbackTag + | JSDocOverloadTag + | JSDocEnumTag + | JSDocParameterTag + | JSDocReturnTag + | JSDocThisTag + | JSDocTypedefTag + | JSDocSeeTag + | JSDocPropertyTag + | JSDocTemplateTag + | JSDocTypeTag + | JSDocThrowsTag + | JSDocSatisfiesTag + | JSDocImportTag; + +/** @internal */ +export type HasIsTypeOnly = + | ImportEqualsDeclaration + | ExportDeclaration + | ExportSpecifier + | ImportClause + | ImportSpecifier; + +/** @internal */ +export type HasComment = + | JSDoc + | JSDocUnknownTag + | JSDocAugmentsTag + | JSDocImplementsTag + | JSDocAuthorTag + | JSDocDeprecatedTag + | JSDocClassTag + | JSDocPublicTag + | JSDocPrivateTag + | JSDocProtectedTag + | JSDocReadonlyTag + | JSDocOverrideTag + | JSDocCallbackTag + | JSDocOverloadTag + | JSDocEnumTag + | JSDocParameterTag + | JSDocReturnTag + | JSDocThisTag + | JSDocTypeTag + | JSDocTemplateTag + | JSDocTypedefTag + | JSDocSeeTag + | JSDocPropertyTag + | JSDocThrowsTag + | JSDocSatisfiesTag + | JSDocImportTag; + export type HasInitializer = | HasExpressionInitializer | ForStatement @@ -1831,6 +2069,7 @@ export type HasExpressionInitializer = | BindingElement | PropertyDeclaration | PropertyAssignment + | PropertySignature | EnumMember; /** @internal @knipignore */ @@ -1910,6 +2149,80 @@ export type HasIllegalModifiers = | MissingDeclaration | NamespaceExportDeclaration; +/** @internal */ +export type InternalHasModifiers = + | HasModifiers + | HasIllegalModifiers; + +/** @internal */ +export type HasSymbol = + | NumericLiteral + | StringLiteral + | NoSubstitutionTemplateLiteral + | Identifier + | TypeParameterDeclaration + | ParameterDeclaration + | PropertySignature + | PropertyDeclaration + | MethodSignature + | MethodDeclaration + | ClassStaticBlockDeclaration + | ConstructorDeclaration + | GetAccessorDeclaration + | SetAccessorDeclaration + | CallSignatureDeclaration + | ConstructSignatureDeclaration + | IndexSignatureDeclaration + | FunctionTypeNode + | ConstructorTypeNode + | TypeLiteralNode + | MappedTypeNode + | NamedTupleMember + | BindingElement + | ObjectLiteralExpression + | PropertyAccessExpression + | ElementAccessExpression + | CallExpression + | NewExpression + | FunctionExpression + | ArrowFunction + | BinaryExpression + | ClassExpression + | VariableDeclaration + | FunctionDeclaration + | ClassDeclaration + | InterfaceDeclaration + | TypeAliasDeclaration + | EnumDeclaration + | ModuleDeclaration + | NamespaceExportDeclaration + | ImportEqualsDeclaration + | ImportDeclaration + | ImportClause + | NamespaceImport + | ImportSpecifier + | ExportAssignment + | ExportDeclaration + | NamespaceExport + | ExportSpecifier + | MissingDeclaration + | JsxAttribute + | JsxAttributes + | SourceFile + | JSDocCallbackTag + | JSDocEnumTag + | JSDocFunctionType + | JSDocSignature + | JSDocTypedefTag + | PropertyAssignment + | ShorthandPropertyAssignment + | SpreadAssignment + | EnumMember + | JSDocParameterTag + | JSDocPropertyTag + | JSDocTypeLiteral + | NotEmittedTypeElement; + /** @internal */ export type PrimitiveLiteral = | BooleanLiteral @@ -1920,6 +2233,21 @@ export type PrimitiveLiteral = | PrefixUnaryExpression & { operator: SyntaxKind.PlusToken; operand: NumericLiteral; } | PrefixUnaryExpression & { operator: SyntaxKind.MinusToken; operand: NumericLiteral | BigIntLiteral; }; +/** @internal */ +export type HasText = + | NumericLiteral + | BigIntLiteral + | StringLiteral + | RegularExpressionLiteral + | TemplateLiteralToken + | JsxText + | JSDocText + | JSDocLink + | JSDocLinkCode + | JSDocLinkPlain + | SourceFile + ; + /** * Declarations that can contain other declarations. Corresponds with `ContainerFlags.IsContainer` in binder.ts. * @@ -2432,15 +2760,65 @@ export type HasName = | JSDocPropertyTag | MissingDeclaration; +// NOTE: Changing the following list requires changes to: +// - `astCanHaveExpression` in ast.ts +// - `astGetExpression` in ast.ts /** @internal */ -export interface DynamicNamedDeclaration extends NamedDeclaration { - readonly name: ComputedPropertyName; -} +export type HasExpression = + | ComputedPropertyName + | TypeParameterDeclaration + | Decorator + | PropertyAccessExpression + | ElementAccessExpression + | CallExpression + | NewExpression + | TypeAssertionExpression + | ParenthesizedExpression + | DeleteExpression + | TypeOfExpression + | VoidExpression + | AwaitExpression + | ForInStatement + | ForOfStatement + | ExpressionStatement + | IfStatement + | DoStatement + | WhileStatement + | YieldExpression + | SpreadElement + | ExpressionWithTypeArguments + | AsExpression + | NonNullExpression + | SatisfiesExpression + | TemplateSpan + | ReturnStatement + | WithStatement + | SwitchStatement + | ThrowStatement + | ExportAssignment + | ExternalModuleReference + | JsxSpreadAttribute + | JsxExpression + | CaseClause + | SpreadAssignment + | PartiallyEmittedExpression + | SyntheticReferenceExpression; /** @internal */ -export interface DynamicNamedBinaryExpression extends BinaryExpression { +export type DynamicNamedDeclaration = NamedDeclaration & { + readonly name: ComputedPropertyName; + readonly data: { + readonly name: AstComputedPropertyName; + }; +}; + +/** @internal */ +export type DynamicNamedBinaryExpression = BinaryExpression & { readonly left: ElementAccessExpression; -} + readonly data: { + readonly left: AstElementAccessExpression; + }; +}; /** @internal */ // A declaration that supports late-binding (used in checker) @@ -4304,10 +4682,14 @@ export class BinaryExpression extends Node; -export interface AssignmentExpression extends BinaryExpression { +export type AssignmentExpression = BinaryExpression & { readonly left: LeftHandSideExpression; readonly operatorToken: TOperator; -} + readonly data: { + readonly left: AstLeftHandSideExpression; + readonly operatorToken: TOperator; + }; +}; export interface ObjectDestructuringAssignment extends AssignmentExpression { readonly left: ObjectLiteralExpression; @@ -5050,7 +5432,7 @@ export class CallExpression extends Node | undefined { return this.ast.data.typeArguments?.nodes; } get arguments(): NodeArray { return this.ast.data.arguments.nodes; } - + /** @internal */ set expression(value) { this.ast.data.expression = value.ast; } /** @internal */ set questionDotToken(value) { this.ast.data.questionDotToken = value?.ast; } /** @internal */ set typeArguments(value) { this.ast.data.typeArguments = value?.ast; } @@ -5086,6 +5468,9 @@ export type OptionalChainRoot = /** @internal */ export type BindableObjectDefinePropertyCall = CallExpression & { readonly arguments: readonly [BindableStaticNameExpression, StringLiteralLike | NumericLiteral, ObjectLiteralExpression] & Readonly; + readonly data: { + readonly arguments: { readonly items: readonly [AstBindableStaticNameExpression, AstStringLiteralLike | AstNumericLiteral, AstObjectLiteralExpression]; } & Readonly + }; }; /** @internal */ @@ -5096,16 +5481,25 @@ export type BindableStaticNameExpression = /** @internal */ export type LiteralLikeElementAccessExpression = ElementAccessExpression & Declaration & { readonly argumentExpression: StringLiteralLike | NumericLiteral; + readonly data: { + readonly argumentExpression: AstStringLiteralLike | AstNumericLiteral; + }; }; /** @internal */ export type BindableStaticElementAccessExpression = LiteralLikeElementAccessExpression & { readonly expression: BindableStaticNameExpression; + readonly data: { + readonly expression: AstBindableStaticNameExpression; + }; }; /** @internal */ export type BindableElementAccessExpression = ElementAccessExpression & { readonly expression: BindableStaticNameExpression; + readonly data: { + readonly expression: AstBindableStaticNameExpression; + }; }; /** @internal */ @@ -5119,14 +5513,20 @@ export type BindableAccessExpression = | BindableElementAccessExpression; /** @internal */ -export interface BindableStaticPropertyAssignmentExpression extends BinaryExpression { +export type BindableStaticPropertyAssignmentExpression = BinaryExpression & { readonly left: BindableStaticAccessExpression; -} + readonly data: { + readonly left: AstBindableStaticAccessExpression; + }; +}; /** @internal */ -export interface BindablePropertyAssignmentExpression extends BinaryExpression { +export type BindablePropertyAssignmentExpression = BinaryExpression & { readonly left: BindableAccessExpression; -} + readonly data: { + readonly left: AstBindableStaticAccessExpression; + }; +}; // see: https://tc39.github.io/ecma262/#prod-SuperCall export interface SuperCall extends CallExpression { @@ -5219,7 +5619,7 @@ export class AsExpression extends Node implements UnaryExpression { +export class TypeAssertionExpression extends Node implements UnaryExpression { declare _unaryExpressionBrand: any; declare _expressionBrand: any; // declare readonly ast: AstTypeAssertion; @@ -6320,9 +6720,23 @@ export type ModuleBody = // TODO(rbuckton): Move after ModuleDeclaration /** @internal */ -export interface AmbientModuleDeclaration extends ModuleDeclaration { +export type AmbientModuleDeclaration = ModuleDeclaration & { + readonly name: StringLiteral; readonly body: ModuleBlock | undefined; -} + readonly data: { + readonly name: AstStringLiteral; + readonly body: AstModuleBlock | undefined; + }; +}; + +// TODO(rbuckton): Move after ModuleDeclaration +/** @internal */ +export type NonGlobalAmbientModuleDeclaration = AmbientModuleDeclaration & { + readonly name: StringLiteral; + readonly data: { + readonly name: AstStringLiteral; + }; +}; // dprint-ignore export class ModuleDeclaration extends Node implements DeclarationStatement, JSDocContainer, LocalsContainer { @@ -6960,13 +7374,13 @@ export class JSDoc extends Node { get tags(): NodeArray | undefined { return this.ast.data.tags?.nodes; } get comment(): string | NodeArray | undefined { - const comment = this.ast.data.comment; + const comment = astGetComment(this.ast); return typeof comment === "string" ? comment : comment?.nodes; } /** @internal */ override set parent(value) { super.parent = value; } /** @internal */ set tags(value) { this.ast.data.tags = value?.ast; } - /** @internal */ set comment(value) { this.ast.data.comment = typeof value === "string" ? value : value?.ast; } + /** @internal */ set comment(value) { astSetComment(this.ast, typeof value === "string" ? value : value?.ast); } } // TODO(rbuckton): Move after JSDocText @@ -6978,13 +7392,13 @@ export class JSDocTag | undefined { - const comment = this.ast.data.comment; + const comment = astGetComment(this.ast); return typeof comment === "string" ? comment : comment?.nodes; } /** @internal */ override set parent(value) { super.parent = value; } /** @internal */ set tagName(value) { this.ast.data.tagName = value.ast; } - /** @internal */ set comment(value) { this.ast.data.comment = typeof value === "string" ? value : value?.ast; } + /** @internal */ set comment(value) { astSetComment(this.ast as AstJSDocUnknownTag, typeof value === "string" ? value : value?.ast); } } // dprint-ignore @@ -7277,13 +7691,18 @@ export class JSDocSignature extends Node i } /** @internal */ -export type PartialSourceFile = +export type PartialSourceFile = & Pick & Partial>; @@ -9482,21 +9901,23 @@ export type SymbolId = number; // dprint-ignore export interface Symbol { - flags: SymbolFlags; // Symbol flags - escapedName: __String; // Name of symbol - declarations?: Declaration[]; // Declarations associated with this symbol - valueDeclaration?: Declaration; // First value declaration of the symbol - members?: SymbolTable; // Class, interface or object literal instance members - exports?: SymbolTable; // Module exports - globalExports?: SymbolTable; // Conditional global UMD exports - /** @internal */ id: SymbolId; // Unique id (used to look up SymbolLinks) - /** @internal */ mergeId: number; // Merge id (used to look up merged symbol) - /** @internal */ parent?: Symbol; // Parent symbol - /** @internal */ exportSymbol?: Symbol; // Exported symbol associated with this symbol + flags: SymbolFlags; // Symbol flags + escapedName: __String; // Name of symbol + readonly declarations?: readonly Declaration[]; // Declarations associated with this symbol + readonly valueDeclaration?: Declaration; // First value declaration of the symbol + members?: SymbolTable; // Class, interface or object literal instance members + exports?: SymbolTable; // Module exports + globalExports?: SymbolTable; // Conditional global UMD exports + /** @internal */ astValueDeclaration?: AstDeclaration; // Declarations associated with this symbol + /** @internal */ astDeclarations?: AstDeclaration[]; // First value declaration of the symbol + /** @internal */ id: SymbolId; // Unique id (used to look up SymbolLinks) + /** @internal */ mergeId: number; // Merge id (used to look up merged symbol) + /** @internal */ parent?: Symbol; // Parent symbol + /** @internal */ exportSymbol?: Symbol; // Exported symbol associated with this symbol /** @internal */ constEnumOnlyModule: boolean | undefined; // True if module contains only const enums or other modules with only const enums - /** @internal */ isReferenced?: SymbolFlags; // True if the symbol is referenced elsewhere. Keeps track of the meaning of a reference in case a symbol is both a type parameter and parameter. - /** @internal */ lastAssignmentPos?: number; // Source position of last node that assigns value to symbol. Negative if it is assigned anywhere definitely - /** @internal */ isReplaceableByMethod?: boolean; // Can this Javascript class property be replaced by a method symbol? + /** @internal */ isReferenced?: SymbolFlags; // True if the symbol is referenced elsewhere. Keeps track of the meaning of a reference in case a symbol is both a type parameter and parameter. + /** @internal */ lastAssignmentPos?: number; // Source position of last node that assigns value to symbol. Negative if it is assigned anywhere definitely + /** @internal */ isReplaceableByMethod?: boolean; // Can this Javascript class property be replaced by a method symbol? /** @internal */ assignmentDeclarationMembers?: Map; // detected late-bound assignment declarations associated with the symbol } @@ -12082,7 +12503,7 @@ export type OuterExpression = /** @internal */ export type WrappedExpression = - | OuterExpression & { readonly expression: WrappedExpression; } + | OuterExpression & { readonly expression: WrappedExpression; readonly data: { readonly expression: AstWrappedExpression>; }; } | T; /** @internal */ diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index eb91b187eca..e58229dcc0a 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -180,21 +180,12 @@ import { getDirectoryPath, getImpliedNodeFormatForEmitWorker, getJSDocAugmentsTag, - getJSDocDeprecatedTagNoCache, getJSDocImplementsTags, - getJSDocOverrideTagNoCache, getJSDocParameterTags, - getJSDocParameterTagsNoCache, - getJSDocPrivateTagNoCache, - getJSDocProtectedTagNoCache, - getJSDocPublicTagNoCache, - getJSDocReadonlyTagNoCache, getJSDocReturnType, getJSDocSatisfiesTag, getJSDocTags, getJSDocType, - getJSDocTypeParameterTags, - getJSDocTypeParameterTagsNoCache, getJSDocTypeTag, getLeadingCommentRanges, getLineAndCharacterOfPosition, @@ -221,7 +212,6 @@ import { HasFlowNode, HasInferredType, HasInitializer, - hasInitializer, HasJSDoc, hasJSDocNodes, HasModifiers, @@ -261,8 +251,7 @@ import { isArrayLiteralExpression, isArrowFunction, isAssertionExpression, - isAstJSDocTypeExpression, - isAutoAccessorPropertyDeclaration, + astIsJSDocTypeExpression, isBigIntLiteral, isBinaryExpression, isBindingElement, @@ -329,7 +318,6 @@ import { isJsxNamespacedName, isJsxOpeningLikeElement, isJsxText, - isLeftHandSideExpression, isLineBreak, isLiteralTypeNode, isMappedTypeNode, @@ -337,7 +325,6 @@ import { isMetaProperty, isMethodDeclaration, isMethodOrAccessor, - isModifierLike, isModuleDeclaration, isModuleOrEnumDeclaration, isNamedDeclaration, @@ -356,7 +343,6 @@ import { isParameterPropertyDeclaration, isParenthesizedExpression, isParenthesizedTypeNode, - isPrefixUnaryExpression, isPrivateIdentifier, isPropertyAccessExpression, isPropertyAssignment, @@ -376,7 +362,6 @@ import { isTypeElement, isTypeLiteralNode, isTypeNode, - isTypeParameterDeclaration, isTypeQueryNode, isTypeReferenceNode, isVariableDeclaration, @@ -499,7 +484,6 @@ import { QuestionQuestionEqualsToken, ReadonlyCollection, ReadonlyTextRange, - RegularExpressionLiteral, removeTrailingDirectorySeparator, RequireOrImportCall, RequireVariableStatement, @@ -538,7 +522,6 @@ import { Statement, StringLiteral, StringLiteralLike, - StringLiteralLikeNode, StringLiteralType, stringToToken, SuperCall, @@ -552,7 +535,6 @@ import { targetOptionDeclaration, TemplateExpression, TemplateLiteral, - TemplateLiteralLikeNode, TemplateLiteralToken, TemplateLiteralTypeSpan, TemplateSpan, @@ -604,7 +586,127 @@ import { WriteFileCallback, WriteFileCallbackData, YieldExpression, + AstCallExpression, + astIsCallExpression, + AstBindableObjectDefinePropertyCall, + astIsPropertyAccessExpression, + astIsIdentifier, + astIdText, + astIsStringOrNumericLiteralLike, + AstBindableStaticNameExpression, + AstEntityNameExpression, + AstPropertyAccessEntityNameExpression, + AstBindableStaticAccessExpression, + AstBindableStaticElementAccessExpression, + astIsObjectLiteralExpression, + AstIdentifier, + RefineNode, + AstLiteralLikeElementAccessExpression, + AstPropertyAccessExpression, + AstAccessExpression, + AstPrivateIdentifier, + AstStringLiteralLike, + AstNumericLiteral, + AstElementAccessExpression, + astSkipOuterExpressions, + astIsElementAccessExpression, + AstAssignmentExpression, + astIsBinaryExpression, + astIsLeftHandSideExpression, + astIsVoidExpression, + astIsNumericLiteral, + AstDeclarationName, + astIsStringLiteralLike, + astIsPrefixUnaryExpression, + AstJSDocEnumTag, + AstJSDocCallbackTag, + AstJSDocTypedefTag, + astGetName, + AstQualifiedName, + AstImportSpecifier, + AstBindingElement, + AstThisContainer, + AstComputedPropertyName, + AstArrowFunction, + astIsClassLike, + astIsClassElement, + astIsClassDeclaration, + astIsFunctionDeclaration, + astIsSourceFile, + AstDeclaration, + AstDynamicNamedBinaryExpression, + AstDynamicNamedDeclaration, + astGetNameOfDeclaration, + astCanHaveModifiers, + astIsParameter, + AstVariableLikeDeclaration, + astHasJSDocNodes, + astGetInitializer, + AstParameterDeclaration, + AstTypeParameterDeclaration, + astGetJSDocParameterTagsNoCache, + astGetJSDocParameterTags, + astGetJSDocTypeParameterTagsNoCache, + astGetJSDocTypeParameterTags, + astIsModuleDeclaration, + AstVariableDeclaration, + astIsVariableStatement, + AstPropertyDeclaration, + AstPropertyAssignment, + astIsExpressionStatement, + astGetJSDocPublicTagNoCache, + astGetJSDocPrivateTagNoCache, + astGetJSDocProtectedTagNoCache, + astGetJSDocReadonlyTagNoCache, + astGetJSDocOverrideTagNoCache, + astGetJSDocDeprecatedTagNoCache, + AstModuleExportName, + astForEachChild, + AstSourceFile, + AstNodeArray, + astIsTypeParameterDeclaration, + astIsClassStaticBlockDeclaration, + astIsPropertySignature, + astIsPropertyDeclaration, + astIsPropertyAssignment, + astIsShorthandPropertyAssignment, + astIsMethodDeclaration, + astIsConstructorDeclaration, + astIsGetAccessorDeclaration, + astIsSetAccessorDeclaration, + astIsNamespaceExportDeclaration, + astIsAutoAccessorPropertyDeclaration, + astIsModifierLike, + AstStatement, + AstPrologueDirective, + AstExpressionStatement, + astGetJSDoc, + astIsDecorator, + astGetModifiers, + astCanHaveDecorators, + astIsExportDeclaration, + astIsNamespaceExport, + AstLiteralLikeNode, + AstStringLiteralLikeNode, + astIsBigIntLiteral, + AstStringLiteral, + astGetRawText, + astGetText, + AstRegularExpressionLiteral, + astGetCombinedNodeFlags, + AstAmbientModuleDeclaration, + AstModuleDeclaration, + astIsStringLiteral, + AstNonGlobalAmbientModuleDeclaration, + NonGlobalAmbientModuleDeclaration, + astIsFunctionLikeOrClassStaticBlockDeclaration, + astIsExternalModule, + astIsJSDocNode, + astIsBindingPattern, + astIsDeclaration, + astCanHaveName, } from "./_namespaces/ts.js"; +import { ReadonlyArrayView } from "./readonlyArray.js"; /** @internal */ export const resolvingEmptyArray: never[] = []; @@ -733,6 +835,17 @@ export function forEachAncestor(node: Node, callback: (n: Node) => T | undefi } } +/** @internal */ +export function astForEachAncestor(node: AstNode, callback: (n: AstNode) => T | undefined | "quit"): T | undefined { + while (node) { + const res = callback(node); + if (res === "quit") return undefined; + if (res !== undefined) return res; + if (astIsSourceFile(node)) return undefined; + node = node.parent; + } +} + /** * Calls `callback` for each entry in the map, returning the first truthy result. * Use `map.forEach` instead for normal iteration. @@ -791,7 +904,12 @@ export function usingSingleLineStringWriter(action: (writer: EmitTextWriter) => } /** @internal */ -export function getFullWidth(node: Node | AstNode): number { +export function getFullWidth(node: Node): number { + return astGetFullWidth(node.ast); +} + +/** @internal */ +export function astGetFullWidth(node: AstNode): number { return node.end - node.pos; } @@ -945,57 +1063,103 @@ export function hasChangesInResolutions( return false; } +// Returns true if this node contains a parse error anywhere underneath it. +/** + * @deprecated use {@link astContainsParseError} + * @internal + */ +export function containsParseError(node: Node): boolean { + return astContainsParseError(node.ast); +} + // Returns true if this node contains a parse error anywhere underneath it. /** @internal */ -export function containsParseError(node: Node | AstNode): boolean { - aggregateChildData(node instanceof AstNode ? node.node : node); // TODO(rbuckton): do not instantiate node +export function astContainsParseError(node: AstNode): boolean { + astAggregateChildData(node); return (node.flags & NodeFlags.ThisNodeOrAnySubNodesHasError) !== 0; } -function aggregateChildData(node: Node): void { +function astAggregateChildData(node: AstNode): void { if (!(node.flags & NodeFlags.HasAggregatedChildData)) { // A node is considered to contain a parse error if: // a) the parser explicitly marked that it had an error // b) any of it's children reported that it had an error. const thisNodeOrAnySubNodesHasError = ((node.flags & NodeFlags.ThisNodeHasError) !== 0) || - forEachChild(node, containsParseError); + astForEachChild(node, astContainsParseError); // If so, mark ourselves accordingly. if (thisNodeOrAnySubNodesHasError) { - (node as Mutable).flags |= NodeFlags.ThisNodeOrAnySubNodesHasError; + node.flags |= NodeFlags.ThisNodeOrAnySubNodesHasError; } // Also mark that we've propagated the child information to this node. This way we can // always consult the bit directly on this node without needing to check its children // again. - (node as Mutable).flags |= NodeFlags.HasAggregatedChildData; + node.flags |= NodeFlags.HasAggregatedChildData; } } -/** @internal */ +/** + * @deprecated use {@link astGetSourceFileOfNode} + * @internal + */ export function getSourceFileOfNode(node: Node): SourceFile; -/** @internal */ +/** + * @deprecated use {@link astGetSourceFileOfNode} + * @internal + */ export function getSourceFileOfNode(node: Node | undefined): SourceFile | undefined; -/** @internal */ export function getSourceFileOfNode(node: Node | undefined): SourceFile | undefined { + return astGetSourceFileOfNode(node?.ast)?.node; +} + +/** @internal */ +export function astGetSourceFileOfNode(node: AstNode): AstSourceFile; +/** @internal */ +export function astGetSourceFileOfNode(node: AstNode | undefined): AstSourceFile | undefined; +export function astGetSourceFileOfNode(node: AstNode | undefined): AstSourceFile | undefined { while (node && node.kind !== SyntaxKind.SourceFile) { node = node.parent; } - return node as SourceFile; + return node as AstSourceFile; } -/** @internal */ +/** + * @deprecated use {@link astGetSourceFileOfModule} + * @internal + */ export function getSourceFileOfModule(module: Symbol): SourceFile | undefined { return getSourceFileOfNode(module.valueDeclaration || getNonAugmentationDeclaration(module)); } /** @internal */ +export function astGetSourceFileOfModule(module: Symbol): AstSourceFile | undefined { + return astGetSourceFileOfNode(module.valueDeclaration?.ast || getNonAugmentationDeclaration(module)?.ast); +} + +/** + * @deprecated use {@link astIsPlainJsFile} + * @internal + */ export function isPlainJsFile(file: SourceFile | undefined, checkJs: boolean | undefined): boolean { - return !!file && (file.scriptKind === ScriptKind.JS || file.scriptKind === ScriptKind.JSX) && !file.checkJsDirective && checkJs === undefined; + return astIsPlainJsFile(file?.ast, checkJs); } /** @internal */ +export function astIsPlainJsFile(file: AstSourceFile | undefined, checkJs: boolean | undefined): boolean { + return !!file && (file.data.scriptKind === ScriptKind.JS || file.data.scriptKind === ScriptKind.JSX) && !file.data.checkJsDirective && checkJs === undefined; +} + +/** + * @deprecated use {@link astIsStatementWithLocals} + * @internal + */ export function isStatementWithLocals(node: Node): boolean { + return astIsStatementWithLocals(node.ast); +} + +/** @internal */ +export function astIsStatementWithLocals(node: AstNode): boolean { switch (node.kind) { case SyntaxKind.Block: case SyntaxKind.CaseBlock: @@ -1053,10 +1217,41 @@ export function getEndLinePosition(line: number, sourceFile: SourceFileLike): nu * Returns a value indicating whether a name is unique globally or within the current file. * Note: This does not consider whether a name appears as a free identifier or not, so at the expression `x.y` this includes both `x` and `y`. * + * @deprecated use {@link astIsFileLevelUniqueName} * @internal */ export function isFileLevelUniqueName(sourceFile: SourceFile, name: string, hasGlobalName?: PrintHandlers["hasGlobalName"]): boolean { - return !(hasGlobalName && hasGlobalName(name)) && !sourceFile.identifiers.has(name); + return astIsFileLevelUniqueName(sourceFile.ast, name, hasGlobalName); +} + +/** + * Returns a value indicating whether a name is unique globally or within the current file. + * Note: This does not consider whether a name appears as a free identifier or not, so at the expression `x.y` this includes both `x` and `y`. + * + * @internal + */ +export function astIsFileLevelUniqueName(sourceFile: AstSourceFile, name: string, hasGlobalName?: PrintHandlers["hasGlobalName"]): boolean { + return !(hasGlobalName && hasGlobalName(name)) && !sourceFile.data.identifiers.has(name); +} + +// Returns true if this node is missing from the actual source code. A 'missing' node is different +// from 'undefined/defined'. When a node is undefined (which can happen for optional nodes +// in the tree), it is definitely missing. However, a node may be defined, but still be +// missing. This happens whenever the parser knows it needs to parse something, but can't +// get anything in the source code that it expects at that location. For example: +// +// let a: ; +// +// Here, the Type in the Type-Annotation is not-optional (as there is a colon in the source +// code). So the parser will attempt to parse out a type, and will create an actual node. +// However, this node will be 'missing' in the sense that no actual source-code/tokens are +// contained within it. +/** + * @deprecated use {@link astNodeIsMissing} + * @internal + */ +export function nodeIsMissing(node: Node | undefined): boolean { + return astNodeIsMissing(node?.ast); } // Returns true if this node is missing from the actual source code. A 'missing' node is different @@ -1072,7 +1267,7 @@ export function isFileLevelUniqueName(sourceFile: SourceFile, name: string, hasG // However, this node will be 'missing' in the sense that no actual source-code/tokens are // contained within it. /** @internal */ -export function nodeIsMissing(node: Node | AstNode | undefined): boolean { +export function astNodeIsMissing(node: AstNode | undefined): boolean { if (node === undefined) { return true; } @@ -1080,33 +1275,50 @@ export function nodeIsMissing(node: Node | AstNode | undefined): boolean { return node.pos === node.end && node.pos >= 0 && node.kind !== SyntaxKind.EndOfFileToken; } -/** @internal */ -export function nodeIsPresent(node: Node | AstNode | undefined): boolean { +/** + * @deprecated use {@link astNodeIsPresent} + * @internal + */ +export function nodeIsPresent(node: Node | undefined): boolean { return !nodeIsMissing(node); } +/** @internal */ +export function astNodeIsPresent(node: AstNode | undefined): boolean { + return !astNodeIsMissing(node); +} + +/** + * Tests whether `child` is a grammar error on `parent`. + * @deprecated use {@link astIsGrammarError} + * @internal + */ +export function isGrammarError(parent: Node, child: Node | NodeArray): boolean { + return astIsGrammarError(parent.ast, child.ast); +} + /** * Tests whether `child` is a grammar error on `parent`. * @internal */ -export function isGrammarError(parent: Node, child: Node | NodeArray): boolean { - if (isTypeParameterDeclaration(parent)) return child === parent.expression; - if (isClassStaticBlockDeclaration(parent)) return child === parent.modifiers; - if (isPropertySignature(parent)) return child === parent.initializer; - if (isPropertyDeclaration(parent)) return child === parent.questionToken && isAutoAccessorPropertyDeclaration(parent); - if (isPropertyAssignment(parent)) return child === parent.modifiers || child === parent.questionToken || child === parent.exclamationToken || isGrammarErrorElement(parent.modifiers, child, isModifierLike); - if (isShorthandPropertyAssignment(parent)) return child === parent.equalsToken || child === parent.modifiers || child === parent.questionToken || child === parent.exclamationToken || isGrammarErrorElement(parent.modifiers, child, isModifierLike); - if (isMethodDeclaration(parent)) return child === parent.exclamationToken; - if (isConstructorDeclaration(parent)) return child === parent.typeParameters || child === parent.type || isGrammarErrorElement(parent.typeParameters, child, isTypeParameterDeclaration); - if (isGetAccessorDeclaration(parent)) return child === parent.typeParameters || isGrammarErrorElement(parent.typeParameters, child, isTypeParameterDeclaration); - if (isSetAccessorDeclaration(parent)) return child === parent.typeParameters || child === parent.type || isGrammarErrorElement(parent.typeParameters, child, isTypeParameterDeclaration); - if (isNamespaceExportDeclaration(parent)) return child === parent.modifiers || isGrammarErrorElement(parent.modifiers, child, isModifierLike); +export function astIsGrammarError(parent: AstNode, child: AstNode | AstNodeArray): boolean { + if (astIsTypeParameterDeclaration(parent)) return child === parent.data.expression; + if (astIsClassStaticBlockDeclaration(parent)) return child === parent.data.modifiers; + if (astIsPropertySignature(parent)) return child === parent.data.initializer; + if (astIsPropertyDeclaration(parent)) return child === parent.data.questionToken && astIsAutoAccessorPropertyDeclaration(parent); + if (astIsPropertyAssignment(parent)) return child === parent.data.modifiers || child === parent.data.questionToken || child === parent.data.exclamationToken || astIsGrammarErrorElement(parent.data.modifiers, child, astIsModifierLike); + if (astIsShorthandPropertyAssignment(parent)) return child === parent.data.equalsToken || child === parent.data.modifiers || child === parent.data.questionToken || child === parent.data.exclamationToken || astIsGrammarErrorElement(parent.data.modifiers, child, astIsModifierLike); + if (astIsMethodDeclaration(parent)) return child === parent.data.exclamationToken; + if (astIsConstructorDeclaration(parent)) return child === parent.data.typeParameters || child === parent.data.type || astIsGrammarErrorElement(parent.data.typeParameters, child, astIsTypeParameterDeclaration); + if (astIsGetAccessorDeclaration(parent)) return child === parent.data.typeParameters || astIsGrammarErrorElement(parent.data.typeParameters, child, astIsTypeParameterDeclaration); + if (astIsSetAccessorDeclaration(parent)) return child === parent.data.typeParameters || child === parent.data.type || astIsGrammarErrorElement(parent.data.typeParameters, child, astIsTypeParameterDeclaration); + if (astIsNamespaceExportDeclaration(parent)) return child === parent.data.modifiers || astIsGrammarErrorElement(parent.data.modifiers, child, astIsModifierLike); return false; } -function isGrammarErrorElement(nodeArray: NodeArray | undefined, child: Node | NodeArray, isElement: (node: Node) => node is T) { - if (!nodeArray || isArray(child) || !isElement(child)) return false; - return contains(nodeArray, child); +function astIsGrammarErrorElement(nodeArray: AstNodeArray | undefined, child: AstNode | AstNodeArray, isElement: (node: AstNode) => node is T) { + if (!nodeArray || child instanceof AstNodeArray || !isElement(child)) return false; + return contains(nodeArray.items, child); } function insertStatementsAfterPrologue(to: T[], from: readonly T[] | undefined, isPrologueDirective: (node: Node) => boolean): T[] { @@ -1122,6 +1334,19 @@ function insertStatementsAfterPrologue(to: T[], from: reado return to; } +function astInsertStatementsAfterPrologue(to: T[], from: readonly T[] | undefined, isPrologueDirective: (node: AstNode) => boolean): T[] { + if (from === undefined || from.length === 0) return to; + let statementIndex = 0; + // skip all prologue directives to insert at the correct position + for (; statementIndex < to.length; ++statementIndex) { + if (!isPrologueDirective(to[statementIndex])) { + break; + } + } + to.splice(statementIndex, 0, ...from); + return to; +} + function insertStatementAfterPrologue(to: T[], statement: T | undefined, isPrologueDirective: (node: Node) => boolean): T[] { if (statement === undefined) return to; let statementIndex = 0; @@ -1135,8 +1360,35 @@ function insertStatementAfterPrologue(to: T[], statement: T return to; } +function astInsertStatementAfterPrologue(to: T[], statement: T | undefined, isPrologueDirective: (node: AstNode) => boolean): T[] { + if (statement === undefined) return to; + let statementIndex = 0; + // skip all prologue directives to insert at the correct position + for (; statementIndex < to.length; ++statementIndex) { + if (!isPrologueDirective(to[statementIndex])) { + break; + } + } + to.splice(statementIndex, 0, statement); + return to; +} + function isAnyPrologueDirective(node: Node) { - return isPrologueDirective(node) || !!(getEmitFlags(node) & EmitFlags.CustomPrologue); + return astIsAnyPrologueDirective(node.ast); +} + +function astIsAnyPrologueDirective(node: AstNode) { + return astIsPrologueDirective(node) || !!(astGetEmitFlags(node) & EmitFlags.CustomPrologue); +} + +/** + * Prepends statements to an array while taking care of prologue directives. + * + * @deprecated use {@link astInsertStatementsAfterStandardPrologue} + * @internal + */ +export function insertStatementsAfterStandardPrologue(to: T[], from: readonly T[] | undefined): T[] { + return insertStatementsAfterPrologue(to, from, isPrologueDirective); } /** @@ -1144,13 +1396,32 @@ function isAnyPrologueDirective(node: Node) { * * @internal */ -export function insertStatementsAfterStandardPrologue(to: T[], from: readonly T[] | undefined): T[] { - return insertStatementsAfterPrologue(to, from, isPrologueDirective); +export function astInsertStatementsAfterStandardPrologue(to: T[], from: readonly T[] | undefined): T[] { + return astInsertStatementsAfterPrologue(to, from, astIsPrologueDirective); +} + +/** + * @deprecated use {@link astInsertStatementsAfterCustomPrologue} + * @internal + */ +export function insertStatementsAfterCustomPrologue(to: T[], from: readonly T[] | undefined): T[] { + return insertStatementsAfterPrologue(to, from, isAnyPrologueDirective); } /** @internal */ -export function insertStatementsAfterCustomPrologue(to: T[], from: readonly T[] | undefined): T[] { - return insertStatementsAfterPrologue(to, from, isAnyPrologueDirective); +export function astInsertStatementsAfterCustomPrologue(to: T[], from: readonly T[] | undefined): T[] { + return astInsertStatementsAfterPrologue(to, from, astIsAnyPrologueDirective); +} + +/** + * Prepends statements to an array while taking care of prologue directives. + * + * @deprecated use {@link astInsertStatementAfterStandardPrologue} + * @internal + * @knipignore + */ +export function insertStatementAfterStandardPrologue(to: T[], statement: T | undefined): T[] { + return insertStatementAfterPrologue(to, statement, isPrologueDirective); } /** @@ -1159,13 +1430,21 @@ export function insertStatementsAfterCustomPrologue(to: T[] * @internal * @knipignore */ -export function insertStatementAfterStandardPrologue(to: T[], statement: T | undefined): T[] { - return insertStatementAfterPrologue(to, statement, isPrologueDirective); +export function astInsertStatementAfterStandardPrologue(to: T[], statement: T | undefined): T[] { + return astInsertStatementAfterPrologue(to, statement, astIsPrologueDirective); +} + +/** + * @deprecated use {@link astInsertStatementAfterCustomPrologue} + * @internal + */ +export function insertStatementAfterCustomPrologue(to: T[], statement: T | undefined): T[] { + return insertStatementAfterPrologue(to, statement, isAnyPrologueDirective); } /** @internal */ -export function insertStatementAfterCustomPrologue(to: T[], statement: T | undefined): T[] { - return insertStatementAfterPrologue(to, statement, isAnyPrologueDirective); +export function astInsertStatementAfterCustomPrologue(to: T[], statement: T | undefined): T[] { + return astInsertStatementAfterPrologue(to, statement, astIsAnyPrologueDirective); } /** @@ -1230,21 +1509,39 @@ export function createCommentDirectivesMap(sourceFile: SourceFile, commentDirect } } -/** @internal */ +/** + * @deprecated use {@link astGetTokenPosOfNode} + * @internal + */ export function getTokenPosOfNode(node: Node, sourceFile?: SourceFileLike, includeJsDoc?: boolean): number { + return astGetTokenPosOfNode(node.ast, sourceFile, includeJsDoc); +} + +function getTextOfContainingSourceFile(node: AstNode, sourceFile: SourceFileLike | AstSourceFile | undefined) { + if (sourceFile instanceof AstNode) { + return sourceFile.data.text; + } + return sourceFile?.text ?? astGetSourceFileOfNode(node).data.text; +} + +/** @internal */ +export function astGetTokenPosOfNode(node: AstNode, sourceFile?: SourceFileLike | AstSourceFile, includeJsDoc?: boolean): number { // With nodes that have no width (i.e. 'Missing' nodes), we actually *don't* // want to skip trivia because this will launch us forward to the next token. - if (nodeIsMissing(node)) { + if (astNodeIsMissing(node)) { return node.pos; } - if (isJSDocNode(node) || node.kind === SyntaxKind.JsxText) { + if (astIsJSDocNode(node) || node.kind === SyntaxKind.JsxText) { // JsxText cannot actually contain comments, even though the scanner will think it sees comments - return skipTrivia((sourceFile ?? getSourceFileOfNode(node)).text, node.pos, /*stopAfterLineBreak*/ false, /*stopAtComments*/ true); + return skipTrivia(getTextOfContainingSourceFile(node, sourceFile), node.pos, /*stopAfterLineBreak*/ false, /*stopAtComments*/ true); // TODO(rbuckton): don't instantiate `.node` } - if (includeJsDoc && hasJSDocNodes(node)) { - return getTokenPosOfNode(node.jsDoc![0], sourceFile); + if (includeJsDoc) { + const jsDoc = firstOrUndefined(astGetJSDoc(node)); + if (jsDoc) { + return astGetTokenPosOfNode(jsDoc.ast, sourceFile); + } } // For a syntax list, it is possible that one of its children has JSDocComment nodes, while @@ -1252,66 +1549,129 @@ export function getTokenPosOfNode(node: Node, sourceFile?: SourceFileLike, inclu // trivia for the list, we may have skipped the JSDocComment as well. So we should process its // first child to determine the actual position of its first token. if (node.kind === SyntaxKind.SyntaxList) { - sourceFile ??= getSourceFileOfNode(node); - const first = firstOrUndefined(getNodeChildren(node, sourceFile)); + sourceFile ??= astGetSourceFileOfNode(node); + if (sourceFile instanceof AstNode) { + sourceFile = sourceFile.node; // TODO(rbuckton): don't instantiate `.node` + } + const first = firstOrUndefined(getNodeChildren(node.node, sourceFile)); // TODO(rbuckton): don't instantiate `.node` if (first) { - return getTokenPosOfNode(first, sourceFile, includeJsDoc); + return astGetTokenPosOfNode(first.ast, sourceFile, includeJsDoc); } } return skipTrivia( - (sourceFile ?? getSourceFileOfNode(node)).text, + getTextOfContainingSourceFile(node, sourceFile), node.pos, /*stopAfterLineBreak*/ false, /*stopAtComments*/ false, - isInJSDoc(node), + astIsInJSDoc(node), ); } -/** @internal */ +/** + * @deprecated use {@link astGetNonDecoratorTokenPosOfNode} + * @internal + */ export function getNonDecoratorTokenPosOfNode(node: Node, sourceFile?: SourceFileLike): number { - const lastDecorator = !nodeIsMissing(node) && canHaveModifiers(node) ? findLast(node.modifiers, isDecorator) : undefined; + return astGetNonDecoratorTokenPosOfNode(node.ast, sourceFile); +} + +/** @internal */ +export function astGetNonDecoratorTokenPosOfNode(node: AstNode, sourceFile?: AstSourceFile | SourceFileLike): number { + const lastDecorator = !astNodeIsMissing(node) && astCanHaveDecorators(node) ? findLast(astGetModifiers(node)?.items, astIsDecorator) : undefined; if (!lastDecorator) { - return getTokenPosOfNode(node, sourceFile); + return astGetTokenPosOfNode(node, sourceFile); } - return skipTrivia((sourceFile || getSourceFileOfNode(node)).text, lastDecorator.end); + return skipTrivia(getTextOfContainingSourceFile(node, sourceFile), lastDecorator.end); } -/** @internal */ +/** + * @deprecated use {@link astGetNonModifierTokenPosOfNode} + * @internal + */ export function getNonModifierTokenPosOfNode(node: Node, sourceFile?: SourceFileLike): number { - const lastModifier = !nodeIsMissing(node) && canHaveModifiers(node) && node.modifiers ? last(node.modifiers) : undefined; - if (!lastModifier) { - return getTokenPosOfNode(node, sourceFile); - } - - return skipTrivia((sourceFile || getSourceFileOfNode(node)).text, lastModifier.end); + return astGetNonModifierTokenPosOfNode(node.ast, sourceFile); } /** @internal */ +export function astGetNonModifierTokenPosOfNode(node: AstNode, sourceFile?: AstSourceFile | SourceFileLike): number { + const lastModifier = !astNodeIsMissing(node) ? lastOrUndefined(astGetModifiers(node)?.items) : undefined; + if (!lastModifier) { + return astGetTokenPosOfNode(node, sourceFile); + } + + return skipTrivia(getTextOfContainingSourceFile(node, sourceFile), lastModifier.end); +} + +/** + * @deprecated use {@link astGetSourceTextOfNodeFromSourceFile} + * @internal + */ export function getSourceTextOfNodeFromSourceFile(sourceFile: SourceFile, node: Node, includeTrivia = false): string { - return getTextOfNodeFromSourceText(sourceFile.text, node, includeTrivia); + return astGetSourceTextOfNodeFromSourceFile(sourceFile.ast, node.ast, includeTrivia); +} + +/** @internal */ +export function astGetSourceTextOfNodeFromSourceFile(sourceFile: AstSourceFile, node: AstNode, includeTrivia = false): string { + return astGetTextOfNodeFromSourceText(sourceFile.data.text, node, includeTrivia); } function isJSDocTypeExpressionOrChild(node: Node | AstNode): boolean { return node instanceof AstNode ? - !!findAncestor(node, isAstJSDocTypeExpression) : + !!findAncestor(node, astIsJSDocTypeExpression) : !!findAncestor(node, isJSDocTypeExpression); } -/** @internal */ +/** + * @deprecated use {@link astIsExportNamespaceAsDefaultDeclaration} + * @internal + */ export function isExportNamespaceAsDefaultDeclaration(node: Node): boolean { - return !!(isExportDeclaration(node) && node.exportClause && isNamespaceExport(node.exportClause) && moduleExportNameIsDefault(node.exportClause.name)); + return astIsExportNamespaceAsDefaultDeclaration(node.ast); } /** @internal */ +export function astIsExportNamespaceAsDefaultDeclaration(node: AstNode): boolean { + return !!(astIsExportDeclaration(node) && node.data.exportClause && astIsNamespaceExport(node.data.exportClause) && astModuleExportNameIsDefault(node.data.exportClause.data.name)); +} + +/** + * @deprecated use {@link astModuleExportNameTextUnescaped} + * @internal + */ export function moduleExportNameTextUnescaped(node: ModuleExportName): string { - return node.kind === SyntaxKind.StringLiteral ? node.text : unescapeLeadingUnderscores(node.escapedText); + return astModuleExportNameTextUnescaped(node.ast); } /** @internal */ +export function astModuleExportNameTextUnescaped(node: AstModuleExportName): string { + return node.kind === SyntaxKind.StringLiteral ? node.data.text : unescapeLeadingUnderscores(node.data.escapedText); +} + +/** + * @deprecated use {@link astModuleExportNameTextEscaped} + * @internal + */ export function moduleExportNameTextEscaped(node: ModuleExportName): __String { - return node.kind === SyntaxKind.StringLiteral ? escapeLeadingUnderscores(node.text) : node.escapedText; + return astModuleExportNameTextEscaped(node.ast); +} + +/** @internal */ +export function astModuleExportNameTextEscaped(node: AstModuleExportName): __String { + return node.kind === SyntaxKind.StringLiteral ? escapeLeadingUnderscores(node.data.text) : node.data.escapedText; +} + +/** + * Equality checks against a keyword without underscores don't need to bother + * to turn "__" into "___" or vice versa, since they will never be equal in + * either case. So we can ignore those cases to improve performance. + * + * @deprecated use {@link astModuleExportNameIsDefault} + * @internal + */ +export function moduleExportNameIsDefault(node: ModuleExportName): boolean { + return astModuleExportNameIsDefault(node.ast); } /** @@ -1321,12 +1681,15 @@ export function moduleExportNameTextEscaped(node: ModuleExportName): __String { * * @internal */ -export function moduleExportNameIsDefault(node: ModuleExportName): boolean { - return (node.kind === SyntaxKind.StringLiteral ? node.text : node.escapedText) === InternalSymbolName.Default; +export function astModuleExportNameIsDefault(node: AstModuleExportName): boolean { + return (node.kind === SyntaxKind.StringLiteral ? node.data.text : node.data.escapedText) === InternalSymbolName.Default; } -/** @internal */ -export function getTextOfNodeFromSourceText(sourceText: string, node: Node | AstNode, includeTrivia = false): string { +/** + * @deprecated use {@link astGetTextOfNodeFromSourceText} + * @internal + */ +export function getTextOfNodeFromSourceText(sourceText: string, node: Node, includeTrivia = false): string { if (nodeIsMissing(node)) { return ""; } @@ -1342,11 +1705,50 @@ export function getTextOfNodeFromSourceText(sourceText: string, node: Node | Ast } /** @internal */ +export function astGetTextOfNodeFromSourceText(sourceText: string, node: AstNode, includeTrivia = false): string { + if (astNodeIsMissing(node)) { + return ""; + } + + let text = sourceText.substring(includeTrivia ? node.pos : skipTrivia(sourceText, node.pos), node.end); + + if (isJSDocTypeExpressionOrChild(node)) { + // strip space + asterisk at line start + text = text.split(/\r\n|\n|\r/).map(line => line.replace(/^\s*\*/, "").trimStart()).join("\n"); + } + + return text; +} + +/** + * @deprecated use {@link astGetTextOfNode} + * @internal + */ export function getTextOfNode(node: Node, includeTrivia = false): string { - return getSourceTextOfNodeFromSourceFile(getSourceFileOfNode(node), node, includeTrivia); + return astGetTextOfNode(node.ast, includeTrivia); +} + +/** @internal */ +export function astGetTextOfNode(node: AstNode, includeTrivia = false): string { + return astGetSourceTextOfNodeFromSourceFile(astGetSourceFileOfNode(node), node, includeTrivia); } function getPos(range: Node) { + return astGetPos(range.ast); +} + +/** + * Note: it is expected that the `nodeArray` and the `node` are within the same file. + * For example, searching for a `SourceFile` in a `SourceFile[]` wouldn't work. + * + * @deprecated use {@link astIndexOfNode} + * @internal + */ +export function indexOfNode(nodeArray: readonly Node[], node: Node): number { + return binarySearch(nodeArray, node, getPos, compareValues); +} + +function astGetPos(range: AstNode) { return range.pos; } @@ -1356,8 +1758,18 @@ function getPos(range: Node) { * * @internal */ -export function indexOfNode(nodeArray: readonly Node[], node: Node): number { - return binarySearch(nodeArray, node, getPos, compareValues); +export function astIndexOfNode(nodeArray: readonly AstNode[], node: AstNode): number { + return binarySearch(nodeArray, node, astGetPos, compareValues); +} + +/** + * Gets flags that control emit behavior of a node. + * + * @deprecated use {@link astGetEmitFlags} + * @internal + */ +export function getEmitFlags(node: Node): EmitFlags { + return astGetEmitFlags(node.ast); } /** @@ -1365,7 +1777,7 @@ export function indexOfNode(nodeArray: readonly Node[], node: Node): number { * * @internal */ -export function getEmitFlags(node: Node): EmitFlags { +export function astGetEmitFlags(node: AstNode): EmitFlags { const emitNode = node.emitNode; return emitNode && emitNode.flags || 0; } @@ -1373,9 +1785,19 @@ export function getEmitFlags(node: Node): EmitFlags { /** * Gets flags that control emit behavior of a node. * + * @deprecated use {@link astGetInternalEmitFlags} * @internal */ export function getInternalEmitFlags(node: Node): InternalEmitFlags { + return astGetInternalEmitFlags(node.ast); +} + +/** + * Gets flags that control emit behavior of a node. + * + * @internal + */ +export function astGetInternalEmitFlags(node: AstNode): InternalEmitFlags { const emitNode = node.emitNode; return emitNode && emitNode.internalFlags || 0; } @@ -1912,12 +2334,37 @@ export const enum GetLiteralTextFlags { AllowNumericSeparator = 1 << 3, } -/** @internal */ +/** + * @deprecated use {@link astGetLiteralText} + * @internal + */ export function getLiteralText(node: LiteralLikeNode, sourceFile: SourceFile | undefined, flags: GetLiteralTextFlags): string { + return astGetLiteralText(node.ast, sourceFile?.ast, flags); +} + +function astCanUseOriginalText(node: AstLiteralLikeNode, flags: GetLiteralTextFlags): boolean { + if (astNodeIsSynthesized(node) || !node.parent || (flags & GetLiteralTextFlags.TerminateUnterminatedLiterals && (node as AstStringLiteralLikeNode).data.isUnterminated)) { + return false; + } + + if (astIsNumericLiteral(node)) { + if (node.data.numericLiteralFlags & TokenFlags.IsInvalid) { + return false; + } + if (node.data.numericLiteralFlags & TokenFlags.ContainsSeparator) { + return !!(flags & GetLiteralTextFlags.AllowNumericSeparator); + } + } + + return !astIsBigIntLiteral(node); +} + +/** @internal */ +export function astGetLiteralText(node: AstLiteralLikeNode, sourceFile: AstSourceFile | undefined, flags: GetLiteralTextFlags): string { // If we don't need to downlevel and we can reach the original source text using // the node's parent reference, then simply get the text as it was originally written. - if (sourceFile && canUseOriginalText(node, flags)) { - return getSourceTextOfNodeFromSourceFile(sourceFile, node); + if (sourceFile && astCanUseOriginalText(node, flags)) { + return astGetSourceTextOfNodeFromSourceFile(sourceFile, node); } // If we can't reach the original source text, use the canonical form if it's a number, @@ -1925,13 +2372,13 @@ export function getLiteralText(node: LiteralLikeNode, sourceFile: SourceFile | u switch (node.kind) { case SyntaxKind.StringLiteral: { const escapeText = flags & GetLiteralTextFlags.JsxAttributeEscape ? escapeJsxAttributeString : - flags & GetLiteralTextFlags.NeverAsciiEscape || (getEmitFlags(node) & EmitFlags.NoAsciiEscaping) ? escapeString : + flags & GetLiteralTextFlags.NeverAsciiEscape || (astGetEmitFlags(node) & EmitFlags.NoAsciiEscaping) ? escapeString : escapeNonAsciiString; - if ((node as StringLiteral).singleQuote) { - return "'" + escapeText(node.text, CharacterCodes.singleQuote) + "'"; + if ((node as AstStringLiteral).data.singleQuote) { + return "'" + escapeText(node.data.text, CharacterCodes.singleQuote) + "'"; } else { - return '"' + escapeText(node.text, CharacterCodes.doubleQuote) + '"'; + return '"' + escapeText(node.data.text, CharacterCodes.doubleQuote) + '"'; } } case SyntaxKind.NoSubstitutionTemplateLiteral: @@ -1940,10 +2387,10 @@ export function getLiteralText(node: LiteralLikeNode, sourceFile: SourceFile | u case SyntaxKind.TemplateTail: { // If a NoSubstitutionTemplateLiteral appears to have a substitution in it, the original text // had to include a backslash: `not \${a} substitution`. - const escapeText = flags & GetLiteralTextFlags.NeverAsciiEscape || (getEmitFlags(node) & EmitFlags.NoAsciiEscaping) ? escapeString : + const escapeText = flags & GetLiteralTextFlags.NeverAsciiEscape || (astGetEmitFlags(node) & EmitFlags.NoAsciiEscaping) ? escapeString : escapeNonAsciiString; - const rawText = (node as TemplateLiteralLikeNode).rawText ?? escapeTemplateSubstitution(escapeText(node.text, CharacterCodes.backtick)); + const rawText = astGetRawText(node) ?? escapeTemplateSubstitution(escapeText(astGetText(node), CharacterCodes.backtick)); switch (node.kind) { case SyntaxKind.NoSubstitutionTemplateLiteral: return "`" + rawText + "`"; @@ -1958,34 +2405,17 @@ export function getLiteralText(node: LiteralLikeNode, sourceFile: SourceFile | u } case SyntaxKind.NumericLiteral: case SyntaxKind.BigIntLiteral: - return node.text; + return node.data.text; case SyntaxKind.RegularExpressionLiteral: - if (flags & GetLiteralTextFlags.TerminateUnterminatedLiterals && (node as RegularExpressionLiteral).isUnterminated) { - return node.text + (node.text.charCodeAt(node.text.length - 1) === CharacterCodes.backslash ? " /" : "/"); + if (flags & GetLiteralTextFlags.TerminateUnterminatedLiterals && (node as AstRegularExpressionLiteral).data.isUnterminated) { + return node.data.text + (node.data.text.charCodeAt(node.data.text.length - 1) === CharacterCodes.backslash ? " /" : "/"); } - return node.text; + return node.data.text; } return Debug.fail(`Literal kind '${node.kind}' not accounted for.`); } -function canUseOriginalText(node: LiteralLikeNode, flags: GetLiteralTextFlags): boolean { - if (nodeIsSynthesized(node) || !node.parent || (flags & GetLiteralTextFlags.TerminateUnterminatedLiterals && (node as StringLiteralLikeNode).isUnterminated)) { - return false; - } - - if (isNumericLiteral(node)) { - if (node.numericLiteralFlags & TokenFlags.IsInvalid) { - return false; - } - if (node.numericLiteralFlags & TokenFlags.ContainsSeparator) { - return !!(flags & GetLiteralTextFlags.AllowNumericSeparator); - } - } - - return !isBigIntLiteral(node); -} - /** @internal */ export function getTextOfConstantValue(value: string | number): string { return isString(value) ? `"${escapeString(value)}"` : "" + value; @@ -1998,31 +2428,66 @@ export function makeIdentifierFromModuleName(moduleName: string): string { return getBaseFileName(moduleName).replace(/^(\d)/, "_$1").replace(/\W/g, "_"); } -/** @internal */ +/** + * @deprecated Use {@link astIsBlockOrCatchScoped} + * @internal + */ export function isBlockOrCatchScoped(declaration: Declaration): boolean { - return (getCombinedNodeFlags(declaration) & NodeFlags.BlockScoped) !== 0 || - isCatchClauseVariableDeclarationOrBindingElement(declaration); + return astIsBlockOrCatchScoped(declaration.ast); } /** @internal */ +export function astIsBlockOrCatchScoped(declaration: AstDeclaration): boolean { + return (astGetCombinedNodeFlags(declaration) & NodeFlags.BlockScoped) !== 0 || + astIsCatchClauseVariableDeclarationOrBindingElement(declaration); +} + +/** + * @deprecated Use {@link astIsCatchClauseVariableDeclarationOrBindingElement} + * @internal + */ export function isCatchClauseVariableDeclarationOrBindingElement(declaration: Declaration): boolean { - const node = getRootDeclaration(declaration); + return astIsCatchClauseVariableDeclarationOrBindingElement(declaration.ast); +} + +/** @internal */ +export function astIsCatchClauseVariableDeclarationOrBindingElement(declaration: AstDeclaration): boolean { + const node = astGetRootDeclaration(declaration); return node.kind === SyntaxKind.VariableDeclaration && node.parent.kind === SyntaxKind.CatchClause; } -/** @internal */ +/** + * @deprecated Use {@link astIsAmbientModule} + * @internal + */ export function isAmbientModule(node: Node): node is AmbientModuleDeclaration { - return isModuleDeclaration(node) && (node.name.kind === SyntaxKind.StringLiteral || isGlobalScopeAugmentation(node)); + return astIsAmbientModule(node.ast); } /** @internal */ +export function astIsAmbientModule(node: AstNode): node is AstAmbientModuleDeclaration { + return astIsModuleDeclaration(node) && (node.data.name.kind === SyntaxKind.StringLiteral || astIsGlobalScopeAugmentation(node)); +} + +/** + * @deprecated Use {@link astIsNonGlobalAmbientModule} + * @internal + */ export function isModuleWithStringLiteralName(node: Node): node is ModuleDeclaration { - return isModuleDeclaration(node) && node.name.kind === SyntaxKind.StringLiteral; + return astIsNonGlobalAmbientModule(node.ast); +} + +/** + * @deprecated Use {@link astIsNonGlobalAmbientModule} + * @internal + */ +export function isNonGlobalAmbientModule(node: Node): node is NonGlobalAmbientModuleDeclaration { + return astIsNonGlobalAmbientModule(node.ast); } /** @internal */ -export function isNonGlobalAmbientModule(node: Node): node is ModuleDeclaration & { name: StringLiteral; } { - return isModuleDeclaration(node) && isStringLiteral(node.name); +export function astIsNonGlobalAmbientModule(node: AstNode): node is AstNonGlobalAmbientModuleDeclaration { + return astIsModuleDeclaration(node) && astIsStringLiteral(node.data.name); } /** @@ -2031,8 +2496,8 @@ export function isNonGlobalAmbientModule(node: Node): node is ModuleDeclaration * 2. A Javascript declaration, which is: * An identifier in a nested property access expression: Y in `X.Y.Z = { ... }` */ -function isEffectiveModuleDeclaration(node: Node) { - return isModuleDeclaration(node) || isIdentifier(node); +function astIsEffectiveModuleDeclaration(node: AstNode) { + return astIsModuleDeclaration(node) || astIsIdentifier(node); } /** @@ -2041,41 +2506,73 @@ function isEffectiveModuleDeclaration(node: Node) { * @internal */ export function isShorthandAmbientModuleSymbol(moduleSymbol: Symbol): boolean { - return isShorthandAmbientModule(moduleSymbol.valueDeclaration); + return isShorthandAmbientModule(moduleSymbol.astValueDeclaration); } -function isShorthandAmbientModule(node: Node | undefined): boolean { +function isShorthandAmbientModule(node: AstNode | undefined): boolean { // The only kind of module that can be missing a body is a shorthand ambient module. - return !!node && node.kind === SyntaxKind.ModuleDeclaration && (!(node as ModuleDeclaration).body); + return !!node && node.kind === SyntaxKind.ModuleDeclaration && (!(node as AstModuleDeclaration).data.body); +} + +/** + * @deprecated Use {@link astIsBlockScopedContainerTopLevel} + * @internal + */ +export function isBlockScopedContainerTopLevel(node: Node): boolean { + return astIsBlockScopedContainerTopLevel(node.ast); } /** @internal */ -export function isBlockScopedContainerTopLevel(node: Node): boolean { +export function astIsBlockScopedContainerTopLevel(node: AstNode): boolean { return node.kind === SyntaxKind.SourceFile || node.kind === SyntaxKind.ModuleDeclaration || - isFunctionLikeOrClassStaticBlockDeclaration(node); + astIsFunctionLikeOrClassStaticBlockDeclaration(node); +} + +/** + * @deprecated Use {@link astIsGlobalScopeAugmentation} + * @internal + */ +export function isGlobalScopeAugmentation(module: ModuleDeclaration): boolean { + return astIsGlobalScopeAugmentation(module.ast); } /** @internal */ -export function isGlobalScopeAugmentation(module: ModuleDeclaration): boolean { +export function astIsGlobalScopeAugmentation(module: AstModuleDeclaration): boolean { return !!(module.flags & NodeFlags.GlobalAugmentation); } -/** @internal */ +/** + * @deprecated Use {@link astIsExternalModuleAugmentation} + * @internal + */ export function isExternalModuleAugmentation(node: Node): node is AmbientModuleDeclaration { return isAmbientModule(node) && isModuleAugmentationExternal(node); } /** @internal */ +export function astIsExternalModuleAugmentation(node: AstNode): node is AstAmbientModuleDeclaration { + return astIsAmbientModule(node) && astIsModuleAugmentationExternal(node); +} + +/** + * @deprecated Use {@link astIsModuleAugmentationExternal} + * @internal + */ export function isModuleAugmentationExternal(node: AmbientModuleDeclaration): boolean { + return astIsModuleAugmentationExternal(node.ast); +} + +/** @internal */ +export function astIsModuleAugmentationExternal(node: AstAmbientModuleDeclaration): boolean { // external module augmentation is a ambient module declaration that is either: // - defined in the top level scope and source file is an external module // - defined inside ambient module declaration located in the top level scope and source file not an external module switch (node.parent.kind) { case SyntaxKind.SourceFile: - return isExternalModule(node.parent); + return astIsExternalModule(node.parent); case SyntaxKind.ModuleBlock: - return isAmbientModule(node.parent.parent) && isSourceFile(node.parent.parent.parent) && !isExternalModule(node.parent.parent.parent); + return astIsAmbientModule(node.parent.parent) && astIsSourceFile(node.parent.parent.parent) && !astIsExternalModule(node.parent.parent.parent); } return false; } @@ -2085,13 +2582,26 @@ export function getNonAugmentationDeclaration(symbol: Symbol): Declaration | und return symbol.declarations?.find(d => !isExternalModuleAugmentation(d) && !(isModuleDeclaration(d) && isGlobalScopeAugmentation(d))); } +/** @internal */ +export function astGetNonAugmentationDeclaration(symbol: Symbol): AstDeclaration | undefined { + return symbol.astDeclarations?.find(d => !astIsExternalModuleAugmentation(d) && !(astIsModuleDeclaration(d) && astIsGlobalScopeAugmentation(d))); +} + function isCommonJSContainingModuleKind(kind: ModuleKind) { return kind === ModuleKind.CommonJS || kind === ModuleKind.Node16 || kind === ModuleKind.NodeNext; } -/** @internal */ +/** + * @deprecated Use {@link astIsEffectiveExternalModule} + * @internal + */ export function isEffectiveExternalModule(node: SourceFile, compilerOptions: CompilerOptions): boolean { - return isExternalModule(node) || (isCommonJSContainingModuleKind(getEmitModuleKind(compilerOptions)) && !!node.commonJsModuleIndicator); + return astIsEffectiveExternalModule(node.ast, compilerOptions); +} + +/** @internal */ +export function astIsEffectiveExternalModule(node: AstSourceFile, compilerOptions: CompilerOptions): boolean { + return astIsExternalModule(node) || (isCommonJSContainingModuleKind(getEmitModuleKind(compilerOptions)) && !!node.data.commonJsModuleIndicator); } /** @@ -2655,10 +3165,18 @@ export function isLiteralImportTypeNode(n: Node): n is LiteralImportTypeNode { return isImportTypeNode(n) && isLiteralTypeNode(n.argument) && isStringLiteral(n.argument.literal); } -/** @internal */ +/** + * @deprecated use {@link astIsPrologueDirective} + * @internal + */ export function isPrologueDirective(node: Node): node is PrologueDirective { + return astIsPrologueDirective(node.ast); +} + +/** @internal */ +export function astIsPrologueDirective(node: AstNode): node is AstPrologueDirective { return node.kind === SyntaxKind.ExpressionStatement - && (node as ExpressionStatement).expression.kind === SyntaxKind.StringLiteral; + && (node as AstExpressionStatement).data.expression.kind === SyntaxKind.StringLiteral; } /** @internal */ @@ -2920,6 +3438,11 @@ export function getMembersOfDeclaration(node: Declaration): NodeArray> { + return (astIsPropertyAccessExpression(node) || astIsLiteralLikeElementAccess(node)) + && astIsModuleIdentifier(node.data.expression) + && astGetElementOrPropertyAccessName(node) === "exports"; } /// Given a BinaryExpression, returns SpecialPropertyAssignmentKind for the various kinds of property /// assignments we treat as special in the binder /** @internal */ export function getAssignmentDeclarationKind(expr: BinaryExpression | CallExpression): AssignmentDeclarationKind { - const special = getAssignmentDeclarationKindWorker(expr); - return special === AssignmentDeclarationKind.Property || isInJSFile(expr) ? special : AssignmentDeclarationKind.None; + return astGetAssignmentDeclarationKind(expr.ast); +} + +/// Given a BinaryExpression, returns SpecialPropertyAssignmentKind for the various kinds of property +/// assignments we treat as special in the binder +/** @internal */ +export function astGetAssignmentDeclarationKind(expr: AstBinaryExpression | AstCallExpression): AssignmentDeclarationKind { + const special = astGetAssignmentDeclarationKindWorker(expr); + return special === AssignmentDeclarationKind.Property || astIsInJSFile(expr) ? special : AssignmentDeclarationKind.None; } /** @internal */ export function isBindableObjectDefinePropertyCall(expr: CallExpression): expr is BindableObjectDefinePropertyCall { - return length(expr.arguments) === 3 && - isPropertyAccessExpression(expr.expression) && - isIdentifier(expr.expression.expression) && - idText(expr.expression.expression) === "Object" && - idText(expr.expression.name) === "defineProperty" && - isStringOrNumericLiteralLike(expr.arguments[1]) && - isBindableStaticNameExpression(expr.arguments[0], /*excludeThisKeyword*/ true); + return astIsBindableObjectDefinePropertyCall(expr.ast); +} + +/** @internal */ +export function astIsBindableObjectDefinePropertyCall(expr: AstCallExpression): expr is AstBindableObjectDefinePropertyCall { + return length(expr.data.arguments.items) === 3 && + astIsPropertyAccessExpression(expr.data.expression) && + astIsIdentifier(expr.data.expression.data.expression) && + astIdText(expr.data.expression.data.expression) === "Object" && + astIdText(expr.data.expression.data.name) === "defineProperty" && + astIsStringOrNumericLiteralLike(expr.data.arguments.items[1]) && + astIsBindableStaticNameExpression(expr.data.arguments.items[0], /*excludeThisKeyword*/ true); } /** @@ -4055,7 +4655,14 @@ function isLiteralLikeAccess(node: Node): node is LiteralLikeElementAccessExpres * x[0] OR x['a'] OR x[Symbol.y] */ function isLiteralLikeElementAccess(node: Node): node is LiteralLikeElementAccessExpression { - return isElementAccessExpression(node) && isStringOrNumericLiteralLike(node.argumentExpression); + return astIsLiteralLikeElementAccess(node.ast); +} + +/** + * x[0] OR x['a'] OR x[Symbol.y] + */ +function astIsLiteralLikeElementAccess(node: AstNode): node is AstLiteralLikeElementAccessExpression { + return astIsElementAccessExpression(node) && astIsStringOrNumericLiteralLike(node.data.argumentExpression); } /** @@ -4064,8 +4671,17 @@ function isLiteralLikeElementAccess(node: Node): node is LiteralLikeElementAcces * @internal */ export function isBindableStaticAccessExpression(node: Node, excludeThisKeyword?: boolean): node is BindableStaticAccessExpression { - return isPropertyAccessExpression(node) && (!excludeThisKeyword && node.expression.kind === SyntaxKind.ThisKeyword || isIdentifier(node.name) && isBindableStaticNameExpression(node.expression, /*excludeThisKeyword*/ true)) - || isBindableStaticElementAccessExpression(node, excludeThisKeyword); + return astIsBindableStaticAccessExpression(node.ast, excludeThisKeyword); +} + +/** + * Any series of property and element accesses. + * + * @internal + */ +export function astIsBindableStaticAccessExpression(node: AstNode, excludeThisKeyword?: boolean): node is AstBindableStaticAccessExpression { + return astIsPropertyAccessExpression(node) && (!excludeThisKeyword && node.data.expression.kind === SyntaxKind.ThisKeyword || astIsIdentifier(node.data.name) && astIsBindableStaticNameExpression(node.data.expression, /*excludeThisKeyword*/ true)) + || astIsBindableStaticElementAccessExpression(node, excludeThisKeyword); } /** @@ -4074,15 +4690,29 @@ export function isBindableStaticAccessExpression(node: Node, excludeThisKeyword? * @internal */ export function isBindableStaticElementAccessExpression(node: Node, excludeThisKeyword?: boolean): node is BindableStaticElementAccessExpression { - return isLiteralLikeElementAccess(node) - && ((!excludeThisKeyword && node.expression.kind === SyntaxKind.ThisKeyword) || - isEntityNameExpression(node.expression) || - isBindableStaticAccessExpression(node.expression, /*excludeThisKeyword*/ true)); + return astIsBindableStaticElementAccessExpression(node.ast, excludeThisKeyword); +} + +/** + * Any series of property and element accesses, ending in a literal element access + * + * @internal + */ +export function astIsBindableStaticElementAccessExpression(node: AstNode, excludeThisKeyword?: boolean): node is AstBindableStaticElementAccessExpression { + return astIsLiteralLikeElementAccess(node) + && ((!excludeThisKeyword && node.data.expression.kind === SyntaxKind.ThisKeyword) || + astIsEntityNameExpression(node.data.expression) || + astIsBindableStaticAccessExpression(node.data.expression, /*excludeThisKeyword*/ true)); } /** @internal */ export function isBindableStaticNameExpression(node: Node, excludeThisKeyword?: boolean): node is BindableStaticNameExpression { - return isEntityNameExpression(node) || isBindableStaticAccessExpression(node, excludeThisKeyword); + return astIsBindableStaticNameExpression(node.ast, excludeThisKeyword); +} + +/** @internal */ +export function astIsBindableStaticNameExpression(node: AstNode, excludeThisKeyword?: boolean): node is AstBindableStaticNameExpression { + return astIsEntityNameExpression(node) || astIsBindableStaticAccessExpression(node, excludeThisKeyword); } /** @internal */ @@ -4093,32 +4723,32 @@ export function getNameOrArgument(expr: PropertyAccessExpression | LiteralLikeEl return expr.argumentExpression; } -function getAssignmentDeclarationKindWorker(expr: BinaryExpression | CallExpression): AssignmentDeclarationKind { - if (isCallExpression(expr)) { - if (!isBindableObjectDefinePropertyCall(expr)) { +function astGetAssignmentDeclarationKindWorker(expr: AstBinaryExpression | AstCallExpression): AssignmentDeclarationKind { + if (astIsCallExpression(expr)) { + if (!astIsBindableObjectDefinePropertyCall(expr)) { return AssignmentDeclarationKind.None; } - const entityName = expr.arguments[0]; - if (isExportsIdentifier(entityName) || isModuleExportsAccessExpression(entityName)) { + const entityName = expr.data.arguments.items[0]; + if (astIsExportsIdentifier(entityName) || astIsModuleExportsAccessExpression(entityName)) { return AssignmentDeclarationKind.ObjectDefinePropertyExports; } - if (isBindableStaticAccessExpression(entityName) && getElementOrPropertyAccessName(entityName) === "prototype") { + if (astIsBindableStaticAccessExpression(entityName) && astGetElementOrPropertyAccessName(entityName) === "prototype") { return AssignmentDeclarationKind.ObjectDefinePrototypeProperty; } return AssignmentDeclarationKind.ObjectDefinePropertyValue; } - if (expr.operatorToken.kind !== SyntaxKind.EqualsToken || !isAccessExpression(expr.left) || isVoidZero(getRightMostAssignedExpression(expr))) { + if (expr.data.operatorToken.kind !== SyntaxKind.EqualsToken || !astIsAccessExpression(expr.data.left) || astIsVoidZero(astGetRightMostAssignedExpression(expr))) { return AssignmentDeclarationKind.None; } - if (isBindableStaticNameExpression(expr.left.expression, /*excludeThisKeyword*/ true) && getElementOrPropertyAccessName(expr.left) === "prototype" && isObjectLiteralExpression(getInitializerOfBinaryExpression(expr))) { + if (astIsBindableStaticNameExpression(expr.data.left.data.expression, /*excludeThisKeyword*/ true) && astGetElementOrPropertyAccessName(expr.data.left) === "prototype" && astIsObjectLiteralExpression(astGetInitializerOfBinaryExpression(expr))) { // F.prototype = { ... } return AssignmentDeclarationKind.Prototype; } - return getAssignmentDeclarationPropertyAccessKind(expr.left); + return astGetAssignmentDeclarationPropertyAccessKind(expr.data.left); } -function isVoidZero(node: Node) { - return isVoidExpression(node) && isNumericLiteral(node.expression) && node.expression.text === "0"; +function astIsVoidZero(node: AstNode) { + return astIsVoidExpression(node) && astIsNumericLiteral(node.data.expression) && node.data.expression.data.text === "0"; } /** @@ -4128,11 +4758,21 @@ function isVoidZero(node: Node) { * @internal */ export function getElementOrPropertyAccessArgumentExpressionOrName(node: AccessExpression): Identifier | PrivateIdentifier | StringLiteralLike | NumericLiteral | ElementAccessExpression | undefined { - if (isPropertyAccessExpression(node)) { - return node.name; + return astGetElementOrPropertyAccessArgumentExpressionOrName(node.ast)?.node; +} + +/** + * Does not handle signed numeric names like `a[+0]` - handling those would require handling prefix unary expressions + * throughout late binding handling as well, which is awkward (but ultimately probably doable if there is demand) + * + * @internal + */ +export function astGetElementOrPropertyAccessArgumentExpressionOrName(node: AstAccessExpression): AstIdentifier | AstPrivateIdentifier | AstStringLiteralLike | AstNumericLiteral | AstElementAccessExpression | undefined { + if (astIsPropertyAccessExpression(node)) { + return node.data.name; } - const arg = skipParentheses(node.argumentExpression); - if (isNumericLiteral(arg) || isStringLiteralLike(arg)) { + const arg = astSkipParentheses(node.data.argumentExpression); + if (astIsNumericLiteral(arg) || astIsStringLiteralLike(arg)) { return arg; } return node; @@ -4144,13 +4784,22 @@ export function getElementOrPropertyAccessName(node: LiteralLikeElementAccessExp export function getElementOrPropertyAccessName(node: AccessExpression): __String | undefined; /** @internal */ export function getElementOrPropertyAccessName(node: AccessExpression): __String | undefined { - const name = getElementOrPropertyAccessArgumentExpressionOrName(node); + return astGetElementOrPropertyAccessName(node.ast); +} + +/** @internal */ +export function astGetElementOrPropertyAccessName(node: AstLiteralLikeElementAccessExpression | AstPropertyAccessExpression): __String; +/** @internal */ +export function astGetElementOrPropertyAccessName(node: AstAccessExpression): __String | undefined; +/** @internal */ +export function astGetElementOrPropertyAccessName(node: AstAccessExpression): __String | undefined { + const name = astGetElementOrPropertyAccessArgumentExpressionOrName(node); if (name) { - if (isIdentifier(name)) { - return name.escapedText; + if (astIsIdentifier(name)) { + return name.data.escapedText; } - if (isStringLiteralLike(name) || isNumericLiteral(name)) { - return escapeLeadingUnderscores(name.text); + if (astIsStringLiteralLike(name) || astIsNumericLiteral(name)) { + return escapeLeadingUnderscores(name.data.text); } } return undefined; @@ -4158,34 +4807,39 @@ export function getElementOrPropertyAccessName(node: AccessExpression): __String /** @internal */ export function getAssignmentDeclarationPropertyAccessKind(lhs: AccessExpression): AssignmentDeclarationKind { - if (lhs.expression.kind === SyntaxKind.ThisKeyword) { + return astGetAssignmentDeclarationPropertyAccessKind(lhs.ast); +} + +/** @internal */ +export function astGetAssignmentDeclarationPropertyAccessKind(lhs: AstAccessExpression): AssignmentDeclarationKind { + if (lhs.data.expression.kind === SyntaxKind.ThisKeyword) { return AssignmentDeclarationKind.ThisProperty; } - else if (isModuleExportsAccessExpression(lhs)) { + else if (astIsModuleExportsAccessExpression(lhs)) { // module.exports = expr return AssignmentDeclarationKind.ModuleExports; } - else if (isBindableStaticNameExpression(lhs.expression, /*excludeThisKeyword*/ true)) { - if (isPrototypeAccess(lhs.expression)) { + else if (astIsBindableStaticNameExpression(lhs.data.expression, /*excludeThisKeyword*/ true)) { + if (astIsPrototypeAccess(lhs.data.expression)) { // F.G....prototype.x = expr return AssignmentDeclarationKind.PrototypeProperty; } let nextToLast = lhs; - while (!isIdentifier(nextToLast.expression)) { - nextToLast = nextToLast.expression as Exclude; + while (!astIsIdentifier(nextToLast.data.expression)) { + nextToLast = nextToLast.data.expression as Exclude; } - const id = nextToLast.expression; + const id = nextToLast.data.expression; if ( - (id.escapedText === "exports" || - id.escapedText === "module" && getElementOrPropertyAccessName(nextToLast) === "exports") && + (id.data.escapedText === "exports" || + id.data.escapedText === "module" && astGetElementOrPropertyAccessName(nextToLast) === "exports") && // ExportsProperty does not support binding with computed names - isBindableStaticAccessExpression(lhs) + astIsBindableStaticAccessExpression(lhs) ) { // exports.name = expr OR module.exports.name = expr OR exports["name"] = expr ... return AssignmentDeclarationKind.ExportsProperty; } - if (isBindableStaticNameExpression(lhs, /*excludeThisKeyword*/ true) || (isElementAccessExpression(lhs) && isDynamicName(lhs))) { + if (astIsBindableStaticNameExpression(lhs, /*excludeThisKeyword*/ true) || (astIsElementAccessExpression(lhs) && astIsDynamicName(lhs))) { // F.G...x = expr return AssignmentDeclarationKind.Property; } @@ -4196,10 +4850,15 @@ export function getAssignmentDeclarationPropertyAccessKind(lhs: AccessExpression /** @internal */ export function getInitializerOfBinaryExpression(expr: BinaryExpression): Expression { - while (isBinaryExpression(expr.right)) { - expr = expr.right; + return astGetInitializerOfBinaryExpression(expr.ast).node; +} + +/** @internal */ +export function astGetInitializerOfBinaryExpression(expr: AstBinaryExpression): AstExpression { + while (astIsBinaryExpression(expr.data.right)) { + expr = expr.data.right; } - return expr.right; + return expr.data.right; } /** @internal */ @@ -4215,23 +4874,33 @@ export function isPrototypePropertyAssignment(node: Node): node is PrototypeProp /** @internal */ export function isSpecialPropertyDeclaration(expr: PropertyAccessExpression | ElementAccessExpression): expr is PropertyAccessExpression | LiteralLikeElementAccessExpression { - return isInJSFile(expr) && + return astIsSpecialPropertyDeclaration(expr.ast); +} + +/** @internal */ +export function astIsSpecialPropertyDeclaration(expr: AstPropertyAccessExpression | AstElementAccessExpression): expr is AstPropertyAccessExpression | AstLiteralLikeElementAccessExpression { + return astIsInJSFile(expr) && expr.parent && expr.parent.kind === SyntaxKind.ExpressionStatement && - (!isElementAccessExpression(expr) || isLiteralLikeElementAccess(expr)) && - !!getJSDocTypeTag(expr.parent); + (!astIsElementAccessExpression(expr) || astIsLiteralLikeElementAccess(expr)) && + !!getJSDocTypeTag(expr.parent.node); // TODO(rbuckton): do not instantiate `.node` } /** @internal */ export function setValueDeclaration(symbol: Symbol, node: Declaration): void { - const { valueDeclaration } = symbol; + astSetValueDeclaration(symbol, node.ast); +} + +/** @internal */ +export function astSetValueDeclaration(symbol: Symbol, node: AstDeclaration): void { + const { astValueDeclaration } = symbol; if ( - !valueDeclaration || - !(node.flags & NodeFlags.Ambient && !isInJSFile(node) && !(valueDeclaration.flags & NodeFlags.Ambient)) && - (isAssignmentDeclaration(valueDeclaration) && !isAssignmentDeclaration(node)) || - (valueDeclaration.kind !== node.kind && isEffectiveModuleDeclaration(valueDeclaration)) + !astValueDeclaration || + !(node.flags & NodeFlags.Ambient && !astIsInJSFile(node) && !(astValueDeclaration.flags & NodeFlags.Ambient)) && + (astIsAssignmentDeclaration(astValueDeclaration) && !astIsAssignmentDeclaration(node)) || + (astValueDeclaration.kind !== node.kind && astIsEffectiveModuleDeclaration(astValueDeclaration)) ) { // other kinds of value declarations take precedence over modules and assignment declarations - symbol.valueDeclaration = node; + symbol.astValueDeclaration = node; } } @@ -4398,6 +5067,11 @@ export function isJSDocConstructSignature(node: Node): boolean { /** @internal */ export function isJSDocTypeAlias(node: Node): node is JSDocTypedefTag | JSDocCallbackTag | JSDocEnumTag { + return astIsJSDocTypeAlias(node.ast); +} + +/** @internal */ +export function astIsJSDocTypeAlias(node: AstNode): node is AstJSDocTypedefTag | AstJSDocCallbackTag | AstJSDocEnumTag { return node.kind === SyntaxKind.JSDocTypedefTag || node.kind === SyntaxKind.JSDocCallbackTag || node.kind === SyntaxKind.JSDocEnumTag; } @@ -4415,37 +5089,55 @@ function getSourceOfAssignment(node: Node): Node | undefined { } function getSourceOfDefaultedAssignment(node: Node): Node | undefined { - return isExpressionStatement(node) && - isBinaryExpression(node.expression) && - getAssignmentDeclarationKind(node.expression) !== AssignmentDeclarationKind.None && - isBinaryExpression(node.expression.right) && - (node.expression.right.operatorToken.kind === SyntaxKind.BarBarToken || node.expression.right.operatorToken.kind === SyntaxKind.QuestionQuestionToken) - ? node.expression.right.right + return astGetSourceOfDefaultedAssignment(node.ast)?.node; +} + +function astGetSourceOfDefaultedAssignment(node: AstNode): AstNode | undefined { + return astIsExpressionStatement(node) && + astIsBinaryExpression(node.data.expression) && + astGetAssignmentDeclarationKind(node.data.expression) !== AssignmentDeclarationKind.None && + astIsBinaryExpression(node.data.expression.data.right) && + (node.data.expression.data.right.data.operatorToken.kind === SyntaxKind.BarBarToken || + node.data.expression.data.right.data.operatorToken.kind === SyntaxKind.QuestionQuestionToken) + ? node.data.expression.data.right.data.right : undefined; } function getSingleInitializerOfVariableStatementOrPropertyDeclaration(node: Node): Expression | undefined { + return astGetSingleInitializerOfVariableStatementOrPropertyDeclaration(node.ast)?.node; +} + +function astGetSingleInitializerOfVariableStatementOrPropertyDeclaration(node: AstNode): AstExpression | undefined { switch (node.kind) { case SyntaxKind.VariableStatement: - const v = getSingleVariableOfVariableStatement(node); - return v && v.initializer; + const v = astGetSingleVariableOfVariableStatement(node); + return v && astGetInitializer(v); case SyntaxKind.PropertyDeclaration: - return (node as PropertyDeclaration).initializer; + return (node as AstPropertyDeclaration).data.initializer; case SyntaxKind.PropertyAssignment: - return (node as PropertyAssignment).initializer; + return (node as AstPropertyAssignment).data.initializer; } } /** @internal */ export function getSingleVariableOfVariableStatement(node: Node): VariableDeclaration | undefined { - return isVariableStatement(node) ? firstOrUndefined(node.declarationList.declarations) : undefined; + return astGetSingleVariableOfVariableStatement(node.ast)?.node; +} + +/** @internal */ +export function astGetSingleVariableOfVariableStatement(node: AstNode): AstVariableDeclaration | undefined { + return astIsVariableStatement(node) ? firstOrUndefined(node.data.declarationList.data.declarations.items) : undefined; } function getNestedModuleDeclaration(node: Node): Node | undefined { - return isModuleDeclaration(node) && - node.body && - node.body.kind === SyntaxKind.ModuleDeclaration - ? node.body + return astGetNestedModuleDeclaration(node.ast)?.node; +} + +function astGetNestedModuleDeclaration(node: AstNode): AstNode | undefined { + return astIsModuleDeclaration(node) && + node.data.body && + node.data.body.kind === SyntaxKind.ModuleDeclaration + ? node.data.body : undefined; } @@ -4577,36 +5269,66 @@ export function getJSDocCommentsAndTags(hostNode: Node): readonly (JSDoc | JSDoc // eslint-disable-next-line @typescript-eslint/unified-signatures export function getJSDocCommentsAndTags(hostNode: Node, noCache?: boolean): readonly (JSDoc | JSDocTag)[]; export function getJSDocCommentsAndTags(hostNode: Node, noCache?: boolean): readonly (JSDoc | JSDocTag)[] { + return astGetJSDocCommentsAndTags(hostNode.ast, noCache); +} + +/** + * This function checks multiple locations for JSDoc comments that apply to a host node. + * At each location, the whole comment may apply to the node, or only a specific tag in + * the comment. In the first case, location adds the entire {@link JSDoc} object. In the + * second case, it adds the applicable {@link JSDocTag}. + * + * For example, a JSDoc comment before a parameter adds the entire {@link JSDoc}. But a + * `@param` tag on the parent function only adds the {@link JSDocTag} for the `@param`. + * + * ```ts + * /** JSDoc will be returned for `a` *\/ + * const a = 0 + * /** + * * Entire JSDoc will be returned for `b` + * * @param c JSDocTag will be returned for `c` + * *\/ + * function b(/** JSDoc will be returned for `c` *\/ c) {} + * ``` + */ +export function astGetJSDocCommentsAndTags(hostNode: AstNode): readonly (JSDoc | JSDocTag)[]; +/** @internal separate signature so that stripInternal can remove noCache from the public API */ +// eslint-disable-next-line @typescript-eslint/unified-signatures +export function astGetJSDocCommentsAndTags(hostNode: AstNode, noCache?: boolean): readonly (JSDoc | JSDocTag)[]; +export function astGetJSDocCommentsAndTags(hostNode: AstNode, noCache?: boolean): readonly (JSDoc | JSDocTag)[] { let result: (JSDoc | JSDocTag)[] | undefined; // Pull parameter comments from declaring function as well - if (isVariableLike(hostNode) && hasInitializer(hostNode) && hasJSDocNodes(hostNode.initializer!)) { - result = addRange(result, filterOwnedJSDocTags(hostNode, hostNode.initializer.jsDoc!)); + if (astIsVariableLike(hostNode)) { + const initializer = astGetInitializer(hostNode); + if (initializer && astHasJSDocNodes(initializer)) { + result = addRange(result, astFilterOwnedJSDocTags(hostNode, initializer.data.jsDoc!)); + } } - let node: Node | undefined = hostNode; + let node: AstNode | undefined = hostNode; while (node && node.parent) { - if (hasJSDocNodes(node)) { - result = addRange(result, filterOwnedJSDocTags(hostNode, node.jsDoc!)); + if (astHasJSDocNodes(node)) { + result = addRange(result, astFilterOwnedJSDocTags(hostNode, node.data.jsDoc!)); } if (node.kind === SyntaxKind.Parameter) { - result = addRange(result, (noCache ? getJSDocParameterTagsNoCache : getJSDocParameterTags)(node as ParameterDeclaration)); + result = addRange(result, (noCache ? astGetJSDocParameterTagsNoCache : astGetJSDocParameterTags)(node as AstParameterDeclaration)); break; } if (node.kind === SyntaxKind.TypeParameter) { - result = addRange(result, (noCache ? getJSDocTypeParameterTagsNoCache : getJSDocTypeParameterTags)(node as TypeParameterDeclaration)); + result = addRange(result, (noCache ? astGetJSDocTypeParameterTagsNoCache : astGetJSDocTypeParameterTags)(node as AstTypeParameterDeclaration)); break; } - node = getNextJSDocCommentLocation(node); + node = astGetNextJSDocCommentLocation(node); } return result || emptyArray; } -function filterOwnedJSDocTags(hostNode: Node, comments: JSDocArray) { +function astFilterOwnedJSDocTags(hostNode: AstNode, comments: JSDocArray) { const lastJsDoc = last(comments); return flatMap(comments, jsDoc => { if (jsDoc === lastJsDoc) { - const ownedTags = filter(jsDoc.tags, tag => ownsJSDocTag(hostNode, tag)); + const ownedTags = filter(jsDoc.tags, tag => astOwnsJSDocTag(hostNode, tag)); return jsDoc.tags === ownedTags ? [jsDoc] : ownedTags; } else { @@ -4619,16 +5341,21 @@ function filterOwnedJSDocTags(hostNode: Node, comments: JSDocArray) { * Determines whether a host node owns a jsDoc tag. A `@type`/`@satisfies` tag attached to a * a ParenthesizedExpression belongs only to the ParenthesizedExpression. */ -function ownsJSDocTag(hostNode: Node, tag: JSDocTag) { +function astOwnsJSDocTag(hostNode: AstNode, tag: JSDocTag) { return !(isJSDocTypeTag(tag) || isJSDocSatisfiesTag(tag)) || !tag.parent || !isJSDoc(tag.parent) || !isParenthesizedExpression(tag.parent.parent) - || tag.parent.parent === hostNode; + || tag.parent.parent.ast === hostNode; } /** @internal */ export function getNextJSDocCommentLocation(node: Node): Node | undefined { + return astGetNextJSDocCommentLocation(node.ast)?.node; +} + +/** @internal */ +export function astGetNextJSDocCommentLocation(node: AstNode): AstNode | undefined { const parent = node.parent; if ( parent.kind === SyntaxKind.PropertyAssignment || @@ -4636,8 +5363,8 @@ export function getNextJSDocCommentLocation(node: Node): Node | undefined { parent.kind === SyntaxKind.PropertyDeclaration || parent.kind === SyntaxKind.ExpressionStatement && node.kind === SyntaxKind.PropertyAccessExpression || parent.kind === SyntaxKind.ReturnStatement || - getNestedModuleDeclaration(parent) || - isAssignmentExpression(node) + astGetNestedModuleDeclaration(parent) || + astIsAssignmentExpression(node) ) { return parent; } @@ -4649,15 +5376,15 @@ export function getNextJSDocCommentLocation(node: Node): Node | undefined { // var x = function(name) { return name.length; } else if ( parent.parent && - (getSingleVariableOfVariableStatement(parent.parent) === node || isAssignmentExpression(parent)) + (astGetSingleVariableOfVariableStatement(parent.parent) === node || astIsAssignmentExpression(parent)) ) { return parent.parent; } else if ( parent.parent && parent.parent.parent && - (getSingleVariableOfVariableStatement(parent.parent.parent) || - getSingleInitializerOfVariableStatementOrPropertyDeclaration(parent.parent.parent) === node || - getSourceOfDefaultedAssignment(parent.parent.parent)) + (astGetSingleVariableOfVariableStatement(parent.parent.parent) || + astGetSingleInitializerOfVariableStatementOrPropertyDeclaration(parent.parent.parent) === node || + astGetSourceOfDefaultedAssignment(parent.parent.parent)) ) { return parent.parent.parent; } @@ -4965,10 +5692,19 @@ export function skipParentheses(node: Expression, excludeJSDocTypeAssertions?: b export function skipParentheses(node: Node, excludeJSDocTypeAssertions?: boolean): Node; /** @internal */ export function skipParentheses(node: Node, excludeJSDocTypeAssertions?: boolean): Node { + return astSkipParentheses(node.ast, excludeJSDocTypeAssertions).node; +} + +/** @internal */ +export function astSkipParentheses(node: AstExpression, excludeJSDocTypeAssertions?: boolean): AstExpression; +/** @internal */ +export function astSkipParentheses(node: AstNode, excludeJSDocTypeAssertions?: boolean): AstNode; +/** @internal */ +export function astSkipParentheses(node: AstNode, excludeJSDocTypeAssertions?: boolean): AstNode { const flags = excludeJSDocTypeAssertions ? OuterExpressionKinds.Parentheses | OuterExpressionKinds.ExcludeJSDocTypeAssertion : OuterExpressionKinds.Parentheses; - return skipOuterExpressions(node, flags); + return astSkipOuterExpressions(node, flags); } // a node is delete target iff. it is PropertyAccessExpression/ElementAccessExpression with parentheses skipped @@ -4996,6 +5732,12 @@ export function isDeclarationName(name: Node): boolean { return !isSourceFile(name) && !isBindingPattern(name) && isDeclaration(name.parent) && name.parent.name === name; } +// True if `name` is the name of a declaration node +/** @internal */ +export function astIsDeclarationName(name: AstNode): boolean { + return !astIsSourceFile(name) && !astIsBindingPattern(name) && astIsDeclaration(name.parent) && astCanHaveName(name.parent) && name.parent.data.name === name; +} + // See GH#16030 /** @internal */ export function getDeclarationFromName(name: Node): Declaration | undefined { @@ -5040,6 +5782,12 @@ export function isLiteralComputedPropertyDeclarationName(node: Node): boolean { // Return true if the given identifier is classified as an IdentifierName /** @internal */ export function isIdentifierName(node: Identifier): boolean { + return astIsIdentifier(node.ast); +} + +// Return true if the given identifier is classified as an IdentifierName +/** @internal */ +export function astIsIdentifierName(node: AstIdentifier): boolean { const parent = node.parent; switch (parent.kind) { case SyntaxKind.PropertyDeclaration: @@ -5052,14 +5800,14 @@ export function isIdentifierName(node: Identifier): boolean { case SyntaxKind.PropertyAssignment: case SyntaxKind.PropertyAccessExpression: // Name in member declaration or property name in property access - return (parent as NamedDeclaration | PropertyAccessExpression).name === node; + return astGetName(parent) === node; case SyntaxKind.QualifiedName: // Name on right hand side of dot in a type query or type reference - return (parent as QualifiedName).right === node; + return (parent as AstQualifiedName).data.right === node; case SyntaxKind.BindingElement: + return (parent as AstBindingElement).data.propertyName === node; case SyntaxKind.ImportSpecifier: - // Property name in binding element or import specifier - return (parent as BindingElement | ImportSpecifier).propertyName === node; + return (parent as AstImportSpecifier).data.propertyName === node; case SyntaxKind.ExportSpecifier: case SyntaxKind.JsxAttribute: case SyntaxKind.JsxSelfClosingElement: @@ -5290,7 +6038,12 @@ export function isStringOrNumericLiteralLike(node: Node): node is StringLiteralL /** @internal */ export function isSignedNumericLiteral(node: Node): node is PrefixUnaryExpression & { operand: NumericLiteral; } { - return isPrefixUnaryExpression(node) && (node.operator === SyntaxKind.PlusToken || node.operator === SyntaxKind.MinusToken) && isNumericLiteral(node.operand); + return astIsSignedNumericLiteral(node.ast); +} + +/** @internal */ +export function astIsSignedNumericLiteral(node: AstNode): node is AstNode { + return astIsPrefixUnaryExpression(node) && (node.data.operator === SyntaxKind.PlusToken || node.data.operator === SyntaxKind.MinusToken) && astIsNumericLiteral(node.data.operand); } /** @@ -5304,18 +6057,37 @@ export function isSignedNumericLiteral(node: Node): node is PrefixUnaryExpressio * @internal */ export function hasDynamicName(declaration: Declaration): declaration is DynamicNamedDeclaration | DynamicNamedBinaryExpression { - const name = getNameOfDeclaration(declaration); - return !!name && isDynamicName(name); + return astHasDynamicName(declaration.ast); +} + +/** + * A declaration has a dynamic name if all of the following are true: + * 1. The declaration has a computed property name. + * 2. The computed name is *not* expressed as a StringLiteral. + * 3. The computed name is *not* expressed as a NumericLiteral. + * 4. The computed name is *not* expressed as a PlusToken or MinusToken + * immediately followed by a NumericLiteral. + * + * @internal + */ +export function astHasDynamicName(declaration: AstDeclaration): declaration is AstDynamicNamedDeclaration | AstDynamicNamedBinaryExpression { + const name = astGetNameOfDeclaration(declaration); + return !!name && astIsDynamicName(name); } /** @internal */ export function isDynamicName(name: DeclarationName): boolean { + return astIsDynamicName(name.ast); +} + +/** @internal */ +export function astIsDynamicName(name: AstDeclarationName): boolean { if (!(name.kind === SyntaxKind.ComputedPropertyName || name.kind === SyntaxKind.ElementAccessExpression)) { return false; } - const expr = isElementAccessExpression(name) ? skipParentheses(name.argumentExpression) : name.expression; - return !isStringOrNumericLiteralLike(expr) && - !isSignedNumericLiteral(expr); + const expr = astIsElementAccessExpression(name) ? astSkipParentheses(name.data.argumentExpression) : name.data.expression; + return !astIsStringOrNumericLiteralLike(expr) && + !astIsSignedNumericLiteral(expr); } /** @internal */ @@ -5524,8 +6296,16 @@ export function isPartOfParameterDeclaration(node: Declaration): boolean { return root.kind === SyntaxKind.Parameter; } -/** @internal */ +/** + * @deprecated Use {@link astGetRootDeclaration} + * @internal + */ export function getRootDeclaration(node: Node): Node { + return astGetRootDeclaration(node.ast).node; +} + +/** @internal */ +export function astGetRootDeclaration(node: AstNode): AstNode { while (node.kind === SyntaxKind.BindingElement) { node = node.parent.parent; } @@ -5547,7 +6327,15 @@ export function nodeStartsNewLexicalEnvironment(node: Node): boolean { } /** @internal */ -export function nodeIsSynthesized(range: TextRange): boolean { +export function nodeIsSynthesized(range: TextRange & { node?: never }): boolean { + return positionIsSynthesized(range.pos) + || positionIsSynthesized(range.end); +} + +/** + * A copy of `nodeIsSynthesized` for `AstNode` to ensure the function remains monomorphic + * @internal */ +export function astNodeIsSynthesized(range: AstNode): boolean { return positionIsSynthesized(range.pos) || positionIsSynthesized(range.end); } @@ -6802,14 +7590,15 @@ export function getAllAccessorDeclarations(declarations: readonly Declaration[] export function getEffectiveTypeAnnotationNode(node: Node): TypeNode | undefined { if (!isInJSFile(node) && isFunctionDeclaration(node)) return undefined; if (isTypeAliasDeclaration(node)) return undefined; // has a .type, is not a type annotation - const type = (node as HasType).type; + const type = getTypeAnnotationNode(node); if (type || !isInJSFile(node)) return type; return isJSDocPropertyLikeTag(node) ? node.typeExpression && node.typeExpression.type : getJSDocType(node); } /** @internal */ export function getTypeAnnotationNode(node: Node): TypeNode | undefined { - return (node as HasType).type; + const type = (node as HasType).type; + return !type || isJSDocReturnTag(type) ? undefined : type; } /** @@ -7103,7 +7892,12 @@ export function hasEffectiveModifier(node: Node, flags: ModifierFlags): boolean /** @internal */ export function hasSyntacticModifier(node: Node, flags: ModifierFlags): boolean { - return !!getSelectedSyntacticModifierFlags(node, flags); + return astHasSyntacticModifier(node.ast, flags); +} + +/** @internal */ +export function astHasSyntacticModifier(node: AstNode, flags: ModifierFlags): boolean { + return !!astGetSelectedSyntacticModifierFlags(node, flags); } /** @internal */ @@ -7132,9 +7926,17 @@ export function hasAmbientModifier(node: Node): boolean { return hasSyntacticModifier(node, ModifierFlags.Ambient); } -/** @internal */ +/** + * @deprecated use {@link astHasAccessorModifier} + * @internal + */ export function hasAccessorModifier(node: Node): boolean { - return hasSyntacticModifier(node, ModifierFlags.Accessor); + return astHasAccessorModifier(node.ast); +} + +/** @internal */ +export function astHasAccessorModifier(node: AstNode): boolean { + return astHasSyntacticModifier(node, ModifierFlags.Accessor); } /** @internal */ @@ -7154,21 +7956,30 @@ export function getSelectedEffectiveModifierFlags(node: Node, flags: ModifierFla /** @internal @knipignore */ export function getSelectedSyntacticModifierFlags(node: Node, flags: ModifierFlags): ModifierFlags { - return getSyntacticModifierFlags(node) & flags; + return astGetSelectedSyntacticModifierFlags(node.ast, flags); +} + +/** @internal @knipignore */ +export function astGetSelectedSyntacticModifierFlags(node: AstNode, flags: ModifierFlags): ModifierFlags { + return astGetSyntacticModifierFlags(node) & flags; } function getModifierFlagsWorker(node: Node, includeJSDoc: boolean, alwaysIncludeJSDoc?: boolean): ModifierFlags { + return astGetModifierFlagsWorker(node.ast, includeJSDoc, alwaysIncludeJSDoc); +} + +function astGetModifierFlagsWorker(node: AstNode, includeJSDoc: boolean, alwaysIncludeJSDoc?: boolean): ModifierFlags { if (node.kind >= SyntaxKind.FirstToken && node.kind <= SyntaxKind.LastToken) { return ModifierFlags.None; } if (!(node.modifierFlagsCache & ModifierFlags.HasComputedFlags)) { - node.modifierFlagsCache = getSyntacticModifierFlagsNoCache(node) | ModifierFlags.HasComputedFlags; + node.modifierFlagsCache = astGetSyntacticModifierFlagsNoCache(node) | ModifierFlags.HasComputedFlags; } - if (alwaysIncludeJSDoc || includeJSDoc && isInJSFile(node)) { + if (alwaysIncludeJSDoc || includeJSDoc && astIsInJSFile(node)) { if (!(node.modifierFlagsCache & ModifierFlags.HasComputedJSDocModifiers) && node.parent) { - node.modifierFlagsCache |= getRawJSDocModifierFlagsNoCache(node) | ModifierFlags.HasComputedJSDocModifiers; + node.modifierFlagsCache |= astGetRawJSDocModifierFlagsNoCache(node) | ModifierFlags.HasComputedJSDocModifiers; } return selectEffectiveModifierFlags(node.modifierFlagsCache); } @@ -7200,20 +8011,35 @@ export function getEffectiveModifierFlagsAlwaysIncludeJSDoc(node: Node): Modifie * @internal */ export function getSyntacticModifierFlags(node: Node): ModifierFlags { - return getModifierFlagsWorker(node, /*includeJSDoc*/ false); + return astGetSyntacticModifierFlags(node.ast); +} + +/** + * Gets the ModifierFlags for syntactic modifiers on the provided node. The modifiers will be cached on the node to improve performance. + * + * NOTE: This function does not use `parent` pointers and will not include modifiers from JSDoc. + * + * @internal + */ +export function astGetSyntacticModifierFlags(node: AstNode): ModifierFlags { + return astGetModifierFlagsWorker(node, /*includeJSDoc*/ false); } function getRawJSDocModifierFlagsNoCache(node: Node): ModifierFlags { + return astGetRawJSDocModifierFlagsNoCache(node.ast); +} + +function astGetRawJSDocModifierFlagsNoCache(node: AstNode): ModifierFlags { let flags = ModifierFlags.None; - if (!!node.parent && !isParameter(node)) { - if (isInJSFile(node)) { - if (getJSDocPublicTagNoCache(node)) flags |= ModifierFlags.JSDocPublic; - if (getJSDocPrivateTagNoCache(node)) flags |= ModifierFlags.JSDocPrivate; - if (getJSDocProtectedTagNoCache(node)) flags |= ModifierFlags.JSDocProtected; - if (getJSDocReadonlyTagNoCache(node)) flags |= ModifierFlags.JSDocReadonly; - if (getJSDocOverrideTagNoCache(node)) flags |= ModifierFlags.JSDocOverride; + if (!!node.parent && !astIsParameter(node)) { + if (astIsInJSFile(node)) { + if (astGetJSDocPublicTagNoCache(node)) flags |= ModifierFlags.JSDocPublic; + if (astGetJSDocPrivateTagNoCache(node)) flags |= ModifierFlags.JSDocPrivate; + if (astGetJSDocProtectedTagNoCache(node)) flags |= ModifierFlags.JSDocProtected; + if (astGetJSDocReadonlyTagNoCache(node)) flags |= ModifierFlags.JSDocReadonly; + if (astGetJSDocOverrideTagNoCache(node)) flags |= ModifierFlags.JSDocOverride; } - if (getJSDocDeprecatedTagNoCache(node)) flags |= ModifierFlags.Deprecated; + if (astGetJSDocDeprecatedTagNoCache(node)) flags |= ModifierFlags.Deprecated; } return flags; @@ -7252,7 +8078,19 @@ export function getEffectiveModifierFlagsNoCache(node: Node): ModifierFlags { * @knipignore */ export function getSyntacticModifierFlagsNoCache(node: Node): ModifierFlags { - let flags = canHaveModifiers(node) ? modifiersToFlags(node.modifiers) : ModifierFlags.None; + return astGetSyntacticModifierFlagsNoCache(node.ast); +} + +/** + * Gets the ModifierFlags for syntactic modifiers on the provided node. The modifier flags cache on the node is ignored. + * + * NOTE: This function does not use `parent` pointers and will not include modifiers from JSDoc. + * + * @internal + * @knipignore + */ +export function astGetSyntacticModifierFlagsNoCache(node: AstNode): ModifierFlags { + let flags = astCanHaveModifiers(node) ? astModifiersToFlags(node.data.modifiers?.items) : ModifierFlags.None; if (node.flags & NodeFlags.NestedNamespace || node.kind === SyntaxKind.Identifier && node.flags & NodeFlags.IdentifierIsInJSDocNamespace) { flags |= ModifierFlags.Export; } @@ -7260,7 +8098,18 @@ export function getSyntacticModifierFlagsNoCache(node: Node): ModifierFlags { } /** @internal */ -export function modifiersToFlags(modifiers: readonly ModifierLike[] | readonly AstModifierLike[] | undefined): ModifierFlags { +export function modifiersToFlags(modifiers: readonly ModifierLike[] | undefined): ModifierFlags { + let flags = ModifierFlags.None; + if (modifiers) { + for (const modifier of modifiers) { + flags |= modifierToFlag(modifier.kind); + } + } + return flags; +} + +/** @internal */ +export function astModifiersToFlags(modifiers: readonly AstModifierLike[] | undefined): ModifierFlags { let flags = ModifierFlags.None; if (modifiers) { for (const modifier of modifiers) { @@ -7383,11 +8232,20 @@ export function isAssignmentExpression(node: Node, excludeCompoundAssignment: tr export function isAssignmentExpression(node: Node, excludeCompoundAssignment?: false): node is AssignmentExpression; /** @internal */ export function isAssignmentExpression(node: Node, excludeCompoundAssignment?: boolean): node is AssignmentExpression { - return isBinaryExpression(node) + return astIsAssignmentExpression(node.ast, excludeCompoundAssignment); +} + +/** @internal */ +export function astIsAssignmentExpression(node: AstNode, excludeCompoundAssignment: true): node is AstAssignmentExpression; +/** @internal */ +export function astIsAssignmentExpression(node: AstNode, excludeCompoundAssignment?: boolean): node is AstAssignmentExpression; +/** @internal */ +export function astIsAssignmentExpression(node: AstNode, excludeCompoundAssignment?: boolean): node is AstAssignmentExpression { + return astIsBinaryExpression(node) && (excludeCompoundAssignment - ? node.operatorToken.kind === SyntaxKind.EqualsToken - : isAssignmentOperator(node.operatorToken.kind)) - && isLeftHandSideExpression(node.left); + ? node.data.operatorToken.kind === SyntaxKind.EqualsToken + : isAssignmentOperator(node.data.operatorToken.kind)) + && astIsLeftHandSideExpression(node.data.left); } /** @internal */ @@ -7408,7 +8266,12 @@ export function isExpressionWithTypeArgumentsInClassExtendsClause(node: Node): n /** @internal */ export function isEntityNameExpression(node: Node): node is EntityNameExpression { - return node.kind === SyntaxKind.Identifier || isPropertyAccessEntityNameExpression(node); + return astIsEntityNameExpression(node.ast); +} + +/** @internal */ +export function astIsEntityNameExpression(node: AstNode): node is AstEntityNameExpression { + return node.kind === SyntaxKind.Identifier || astIsPropertyAccessEntityNameExpression(node); } /** @internal */ @@ -7443,7 +8306,12 @@ export function isDottedName(node: Expression): boolean { /** @internal */ export function isPropertyAccessEntityNameExpression(node: Node): node is PropertyAccessEntityNameExpression { - return isPropertyAccessExpression(node) && isIdentifier(node.name) && isEntityNameExpression(node.expression); + return astIsPropertyAccessEntityNameExpression(node.ast); +} + +/** @internal */ +export function astIsPropertyAccessEntityNameExpression(node: AstNode): node is AstPropertyAccessEntityNameExpression { + return astIsPropertyAccessExpression(node) && astIsIdentifier(node.data.name) && astIsEntityNameExpression(node.data.expression); } /** @internal */ @@ -7471,7 +8339,12 @@ export function tryGetPropertyAccessOrIdentifierToString(expr: Expression | JsxT /** @internal */ export function isPrototypeAccess(node: Node): node is BindableStaticAccessExpression { - return isBindableStaticAccessExpression(node) && getElementOrPropertyAccessName(node) === "prototype"; + return astIsPrototypeAccess(node.ast); +} + +/** @internal */ +export function astIsPrototypeAccess(node: AstNode): node is AstBindableStaticAccessExpression { + return astIsBindableStaticAccessExpression(node) && astGetElementOrPropertyAccessName(node) === "prototype"; } /** @internal */ @@ -8258,6 +9131,11 @@ export function isTypeNodeKind(kind: SyntaxKind): kind is TypeNodeSyntaxKind { /** @internal */ export function isAccessExpression(node: Node): node is AccessExpression { + return astIsAccessExpression(node.ast); +} + +/** @internal */ +export function astIsAccessExpression(node: AstNode): node is AstAccessExpression { return node.kind === SyntaxKind.PropertyAccessExpression || node.kind === SyntaxKind.ElementAccessExpression; } @@ -8368,23 +9246,36 @@ export interface ObjectAllocator { getSourceMapSourceConstructor(): new (fileName: string, text: string, skipTrivia?: (pos: number) => number) => SourceMapSource; } -function Symbol(this: Symbol, flags: SymbolFlags, name: __String): void { - // Note: if modifying this, be sure to update SymbolObject in src/services/services.ts - this.flags = flags; - this.escapedName = name; - this.declarations = undefined; - this.valueDeclaration = undefined; - this.id = 0; - this.mergeId = 0; - this.parent = undefined; - this.members = undefined; - this.exports = undefined; - this.exportSymbol = undefined; - this.constEnumOnlyModule = undefined; - this.isReferenced = undefined; - this.lastAssignmentPos = undefined; - (this as any).links = undefined; // used by TransientSymbol -} +// dprint-ignore +const Symbol: new (flags: SymbolFlags, name: __String) => Symbol = class implements Symbol { + flags: SymbolFlags = 0; + escapedName: __String = "" as __String; + private _declarations: readonly Declaration[] | undefined = undefined; + astValueDeclaration: AstDeclaration | undefined = undefined; + astDeclarations: AstDeclaration[] | undefined = undefined; + id: number = 0; + mergeId: number = 0; + parent: Symbol | undefined = undefined; + members: SymbolTable | undefined = undefined; + exports: SymbolTable | undefined = undefined; + exportSymbol: Symbol | undefined = undefined; + constEnumOnlyModule: boolean | undefined = undefined; + isReferenced: SymbolFlags | undefined = undefined; + lastAssignmentPos: number | undefined = undefined; + globalExports: SymbolTable | undefined = undefined; + isReplaceableByMethod: boolean | undefined = undefined; + assignmentDeclarationMembers: Map | undefined = undefined; + links: unknown = undefined; // used by TransientSymbol + + constructor(flags: SymbolFlags, name: __String) { + this.flags = flags; + this.escapedName = name; + } + + get valueDeclaration() { return this.astValueDeclaration?.node; } + set valueDeclaration(value) { this.astValueDeclaration = value?.ast; } + get declarations() { return this._declarations ??= this.astDeclarations && new ReadonlyArrayView(this.astDeclarations, ast => ast.node); } +}; function Type(this: Type, checker: TypeChecker, flags: TypeFlags): void { // Note: if modifying this, be sure to update TypeObject in src/services/services.ts diff --git a/src/compiler/utilitiesPublic.ts b/src/compiler/utilitiesPublic.ts index 4dc62edbd2b..00dae06868e 100644 --- a/src/compiler/utilitiesPublic.ts +++ b/src/compiler/utilitiesPublic.ts @@ -1,6 +1,5 @@ import { __String, - AccessExpression, AccessorDeclaration, ArrayBindingElement, ArrayBindingOrAssignmentElement, @@ -11,7 +10,6 @@ import { AssignmentPattern, AutoAccessorPropertyDeclaration, BinaryExpression, - BindableObjectDefinePropertyCall, BindingElement, BindingName, BindingOrAssignmentElement, @@ -51,13 +49,11 @@ import { Diagnostics, diagnosticsEqualityComparer, ElementAccessChain, - ElementAccessExpression, emptyArray, EntityName, entityNameToString, EnumDeclaration, every, - ExportAssignment, ExportDeclaration, ExportSpecifier, Expression, @@ -76,11 +72,9 @@ import { GeneratedIdentifierFlags, GeneratedPrivateIdentifier, GetAccessorDeclaration, - getAssignmentDeclarationKind, getDirectoryPath, getEffectiveModifierFlags, getEffectiveModifierFlagsAlwaysIncludeJSDoc, - getElementOrPropertyAccessArgumentExpressionOrName, getEmitScriptTarget, getJSDocCommentsAndTags, getJSDocRoot, @@ -106,21 +100,17 @@ import { ImportEqualsDeclaration, ImportSpecifier, ImportTypeNode, - isAccessExpression, isAmbientModule, isAnyImportOrReExport, isArrowFunction, isAssignmentExpression, - isBinaryExpression, isBindableStaticAccessExpression, - isBindableStaticElementAccessExpression, isBindableStaticNameExpression, isBindingElement, isBlock, isCallExpression, isCallSignatureDeclaration, isClassExpression, - isClassStaticBlockDeclaration, isDecorator, isElementAccessExpression, isExpandoPropertyDeclaration, @@ -163,7 +153,6 @@ import { isParameter, isPrivateIdentifier, isPropertyAccessExpression, - isPropertyAssignment, isPropertyDeclaration, isPrototypeAccess, isRootedDiskPath, @@ -296,6 +285,56 @@ import { HasAsteriskToken, AsteriskToken, AstNode, + AstIdentifier, + AstPrivateIdentifier, + AstClassLikeDeclaration, + AstClassElement, + AstDeclaration, + AstExpression, + AstDeclarationName, + astIsFunctionExpression, + astIsArrowFunction, + astIsClassExpression, + AstJSDocPropertyLikeTag, + AstCallExpression, + AstBinaryExpression, + astGetAssignmentDeclarationKind, + astGetElementOrPropertyAccessArgumentExpressionOrName, + AstAccessExpression, + AstBindableObjectDefinePropertyCall, + AstJSDocTypedefTag, + AstJSDocEnumTag, + AstExportAssignment, + astIsIdentifier, + AstElementAccessExpression, + astIsBindableStaticElementAccessExpression, + astGetName, + AstNamedDeclaration, + astIsInJSFile, + astIsExpression, + AstPropertyAccessExpression, + astCanHaveJSDoc, + astGetJSDocCommentsAndTags, + AstParameterDeclaration, + AstTypeParameterDeclaration, + astIsPropertyAssignment, + astIsBindingElement, + astIsBinaryExpression, + astIsAccessExpression, + astIsVariableDeclaration, + AstAutoAccessorPropertyDeclaration, + astIsPropertyDeclaration, + astHasAccessorModifier, + AstModifierLike, + AstModifier, + astIsDecorator, + AstBindingElement, + AstVariableDeclaration, + AstSignatureDeclaration, + AstClassStaticBlockDeclaration, + astIsClassStaticBlockDeclaration, + isDeclarationName, + AstBindingPattern, } from "./_namespaces/ts.js"; export function isExternalModuleNameRelative(moduleName: string): boolean { @@ -638,6 +677,15 @@ export function walkUpBindingElementsAndPatterns(binding: BindingElement): Varia return node.parent; } +/** @internal */ +export function astWalkUpBindingElementsAndPatterns(binding: AstBindingElement): AstVariableDeclaration | AstParameterDeclaration { + let node = binding.parent; + while (astIsBindingElement(node.parent)) { + node = node.parent.parent; + } + return node.parent; +} + function getCombinedFlags(node: Node, getFlags: (n: Node) => number): number { if (isBindingElement(node)) { node = walkUpBindingElementsAndPatterns(node); @@ -656,6 +704,24 @@ function getCombinedFlags(node: Node, getFlags: (n: Node) => number): number { return flags; } +function astGetCombinedFlags(node: AstNode, getFlags: (n: AstNode) => number): number { + if (astIsBindingElement(node)) { + node = astWalkUpBindingElementsAndPatterns(node); + } + let flags = getFlags(node); + if (node.kind === SyntaxKind.VariableDeclaration) { + node = node.parent; + } + if (node && node.kind === SyntaxKind.VariableDeclarationList) { + flags |= getFlags(node); + node = node.parent; + } + if (node && node.kind === SyntaxKind.VariableStatement) { + flags |= getFlags(node); + } + return flags; +} + export function getCombinedModifierFlags(node: Declaration): ModifierFlags { return getCombinedFlags(node, getEffectiveModifierFlags); } @@ -673,10 +739,22 @@ export function getCombinedNodeFlagsAlwaysIncludeJSDoc(node: Declaration): Modif // list. By calling this function, all those flags are combined so that the client can treat // the node as if it actually had those flags. export function getCombinedNodeFlags(node: Node): NodeFlags { - return getCombinedFlags(node, getNodeFlags); + return astGetCombinedNodeFlags(node.ast); } -function getNodeFlags(node: Node) { +// Returns the node flags for this node and all relevant parent nodes. This is done so that +// nodes like variable declarations and binding elements can returned a view of their flags +// that includes the modifiers from their container. i.e. flags like export/declare aren't +// stored on the variable declaration directly, but on the containing variable statement +// (if it has one). Similarly, flags for let/const are stored on the variable declaration +// list. By calling this function, all those flags are combined so that the client can treat +// the node as if it actually had those flags. +/** @internal */ +export function astGetCombinedNodeFlags(node: AstNode): NodeFlags { + return astGetCombinedFlags(node, astGetNodeFlags); +} + +function astGetNodeFlags(node: AstNode) { return node.flags; } @@ -872,12 +950,28 @@ export function idText(identifierOrPrivateName: Identifier | PrivateIdentifier): return unescapeLeadingUnderscores(identifierOrPrivateName.escapedText); } +export function astIdText(identifierOrPrivateName: AstIdentifier | AstPrivateIdentifier): string { + // NOTE: each branch is duplicated to remain monomorphic + switch (identifierOrPrivateName.kind) { + case SyntaxKind.Identifier: return unescapeLeadingUnderscores(identifierOrPrivateName.data.escapedText); + case SyntaxKind.PrivateIdentifier: return unescapeLeadingUnderscores(identifierOrPrivateName.data.escapedText); + } +} + /** * If the text of an Identifier matches a keyword (including contextual and TypeScript-specific keywords), returns the * SyntaxKind for the matching keyword. */ export function identifierToKeywordKind(node: Identifier): KeywordSyntaxKind | undefined { - const token = stringToToken(node.escapedText as string); + return astIdentifierToKeywordKind(node.ast); +} + +/** + * If the text of an Identifier matches a keyword (including contextual and TypeScript-specific keywords), returns the + * SyntaxKind for the matching keyword. + */ +export function astIdentifierToKeywordKind(node: AstIdentifier): KeywordSyntaxKind | undefined { + const token = stringToToken(node.data.escapedText as string); return token ? tryCast(token, isKeyword) : undefined; } @@ -894,51 +988,60 @@ export function symbolName(symbol: Symbol): string { * will be merged with) */ function nameForNamelessJSDocTypedef(declaration: JSDocTypedefTag | JSDocEnumTag): Identifier | PrivateIdentifier | undefined { + return astNameForNamelessJSDocTypedef(declaration.ast)?.node; +} + +/** + * A JSDocTypedef tag has an _optional_ name field - if a name is not directly present, we should + * attempt to draw the name from the node the declaration is on (as that declaration is what its' symbol + * will be merged with) + */ +function astNameForNamelessJSDocTypedef(declaration: AstJSDocTypedefTag | AstJSDocEnumTag): AstIdentifier | AstPrivateIdentifier | undefined { const hostNode = declaration.parent.parent; if (!hostNode) { return undefined; } // Covers classes, functions - any named declaration host node - if (isDeclaration(hostNode)) { - return getDeclarationIdentifier(hostNode); + if (astIsDeclaration(hostNode)) { + return astGetDeclarationIdentifier(hostNode); } // Covers remaining cases (returning undefined if none match). switch (hostNode.kind) { case SyntaxKind.VariableStatement: - if (hostNode.declarationList && hostNode.declarationList.declarations[0]) { - return getDeclarationIdentifier(hostNode.declarationList.declarations[0]); + if (hostNode.data.declarationList?.data.declarations.items[0]) { + return astGetDeclarationIdentifier(hostNode.data.declarationList.data.declarations.items[0]); } break; case SyntaxKind.ExpressionStatement: - let expr = hostNode.expression; - if (expr.kind === SyntaxKind.BinaryExpression && (expr as BinaryExpression).operatorToken.kind === SyntaxKind.EqualsToken) { - expr = (expr as BinaryExpression).left; + let expr = hostNode.data.expression; + if (expr.kind === SyntaxKind.BinaryExpression && (expr as AstBinaryExpression).data.operatorToken.kind === SyntaxKind.EqualsToken) { + expr = (expr as AstBinaryExpression).data.left; } switch (expr.kind) { case SyntaxKind.PropertyAccessExpression: - return (expr as PropertyAccessExpression).name; + return (expr as AstPropertyAccessExpression).data.name; case SyntaxKind.ElementAccessExpression: - const arg = (expr as ElementAccessExpression).argumentExpression; - if (isIdentifier(arg)) { + const arg = (expr as AstElementAccessExpression).data.argumentExpression; + if (astIsIdentifier(arg)) { return arg; } } break; case SyntaxKind.ParenthesizedExpression: { - return getDeclarationIdentifier(hostNode.expression); + return astGetDeclarationIdentifier(hostNode.data.expression); } case SyntaxKind.LabeledStatement: { - if (isDeclaration(hostNode.statement) || isExpression(hostNode.statement)) { - return getDeclarationIdentifier(hostNode.statement); + if (astIsDeclaration(hostNode.data.statement) || astIsExpression(hostNode.data.statement)) { + return astGetDeclarationIdentifier(hostNode.data.statement); } break; } } } -function getDeclarationIdentifier(node: Declaration | Expression): Identifier | undefined { - const name = getNameOfDeclaration(node); - return name && isIdentifier(name) ? name : undefined; +function astGetDeclarationIdentifier(node: AstDeclaration | AstExpression): AstIdentifier | undefined { + const name = astGetNameOfDeclaration(node); + return name && astIsIdentifier(name) ? name : undefined; } /** @internal */ @@ -956,6 +1059,10 @@ export function getNameOfJSDocTypedef(declaration: JSDocTypedefTag): Identifier return declaration.name || nameForNamelessJSDocTypedef(declaration); } +export function astGetNameOfJSDocTypedef(declaration: AstJSDocTypedefTag): AstIdentifier | AstPrivateIdentifier | undefined { + return declaration.data.name || astNameForNamelessJSDocTypedef(declaration); +} + /** @internal */ export function isNamedDeclaration(node: Node): node is NamedDeclaration & { name: DeclarationName; } { return !!(node as NamedDeclaration).name; // A 'name' property should always be a DeclarationName. @@ -1055,49 +1162,73 @@ export function hasAsteriskToken(node: Node): node is HasAsteriskToken & { aster /** @internal */ export function getNonAssignedNameOfDeclaration(declaration: Declaration | Expression): DeclarationName | undefined { + return astGetNonAssignedNameOfDeclaration(declaration.ast)?.node; +} + +/** @internal */ +export function astGetNonAssignedNameOfDeclaration(declaration: AstDeclaration | AstExpression): AstDeclarationName | undefined { switch (declaration.kind) { case SyntaxKind.Identifier: - return declaration as Identifier; + return declaration as AstIdentifier; case SyntaxKind.JSDocPropertyTag: case SyntaxKind.JSDocParameterTag: { - const { name } = declaration as JSDocPropertyLikeTag; + const { data: { name } } = declaration as AstJSDocPropertyLikeTag; if (name.kind === SyntaxKind.QualifiedName) { - return name.right; + return name.data.right; } break; } case SyntaxKind.CallExpression: case SyntaxKind.BinaryExpression: { - const expr = declaration as BinaryExpression | CallExpression; - switch (getAssignmentDeclarationKind(expr)) { + const expr = declaration as AstBinaryExpression | AstCallExpression; + switch (astGetAssignmentDeclarationKind(expr)) { case AssignmentDeclarationKind.ExportsProperty: case AssignmentDeclarationKind.ThisProperty: case AssignmentDeclarationKind.Property: case AssignmentDeclarationKind.PrototypeProperty: - return getElementOrPropertyAccessArgumentExpressionOrName((expr as BinaryExpression).left as AccessExpression); + return astGetElementOrPropertyAccessArgumentExpressionOrName((expr as AstBinaryExpression).data.left as AstAccessExpression); case AssignmentDeclarationKind.ObjectDefinePropertyValue: case AssignmentDeclarationKind.ObjectDefinePropertyExports: case AssignmentDeclarationKind.ObjectDefinePrototypeProperty: - return (expr as BindableObjectDefinePropertyCall).arguments[1]; + return (expr as AstBindableObjectDefinePropertyCall).data.arguments.items[1]; default: return undefined; } } case SyntaxKind.JSDocTypedefTag: - return getNameOfJSDocTypedef(declaration as JSDocTypedefTag); + return astGetNameOfJSDocTypedef(declaration as AstJSDocTypedefTag); case SyntaxKind.JSDocEnumTag: - return nameForNamelessJSDocTypedef(declaration as JSDocEnumTag); + return astNameForNamelessJSDocTypedef(declaration as AstJSDocEnumTag); case SyntaxKind.ExportAssignment: { - const { expression } = declaration as ExportAssignment; - return isIdentifier(expression) ? expression : undefined; + const { data: { expression } } = declaration as AstExportAssignment; + return astIsIdentifier(expression) ? expression : undefined; } case SyntaxKind.ElementAccessExpression: - const expr = declaration as ElementAccessExpression; - if (isBindableStaticElementAccessExpression(expr)) { - return expr.argumentExpression; + const expr = declaration as AstElementAccessExpression; + if (astIsBindableStaticElementAccessExpression(expr)) { + return expr.data.argumentExpression; } } - return (declaration as NamedDeclaration).name; + const name = astGetName(declaration); + if (name) { + Debug.type(name); + switch (name.kind) { + case SyntaxKind.NumericLiteral: + case SyntaxKind.BigIntLiteral: + case SyntaxKind.StringLiteral: + case SyntaxKind.NoSubstitutionTemplateLiteral: + case SyntaxKind.Identifier: + case SyntaxKind.PrivateIdentifier: + case SyntaxKind.ComputedPropertyName: + case SyntaxKind.ObjectBindingPattern: + case SyntaxKind.ArrayBindingPattern: + case SyntaxKind.JsxNamespacedName: + return name; + default: + Debug.assertNeverTypeOnly(name); + } + } + return undefined; } export function getNameOfDeclaration(declaration: Declaration | Expression | undefined): DeclarationName | undefined { @@ -1106,24 +1237,39 @@ export function getNameOfDeclaration(declaration: Declaration | Expression | und (isFunctionExpression(declaration) || isArrowFunction(declaration) || isClassExpression(declaration) ? getAssignedName(declaration) : undefined); } +export function astGetNameOfDeclaration(declaration: AstDeclaration | AstExpression | undefined): AstDeclarationName | undefined { + if (declaration === undefined) return undefined; + return astGetNonAssignedNameOfDeclaration(declaration) || + (astIsFunctionExpression(declaration) || astIsArrowFunction(declaration) || astIsClassExpression(declaration) ? astGetAssignedName(declaration) : undefined); +} + /** @internal */ export function getAssignedName(node: Node): DeclarationName | undefined { + return astGetAssignedName(node.ast)?.node; +} + +/** @internal */ +export function astGetAssignedName(node: AstNode): AstDeclarationName | undefined { + // NOTE: branches may be repeated to remain monomorphic if (!node.parent) { return undefined; } - else if (isPropertyAssignment(node.parent) || isBindingElement(node.parent)) { - return node.parent.name; + else if (astIsPropertyAssignment(node.parent)) { + return node.parent.data.name; } - else if (isBinaryExpression(node.parent) && node === node.parent.right) { - if (isIdentifier(node.parent.left)) { - return node.parent.left; + else if (astIsBindingElement(node.parent)) { + return node.parent.data.name; + } + else if (astIsBinaryExpression(node.parent) && node === node.parent.data.right) { + if (astIsIdentifier(node.parent.data.left)) { + return node.parent.data.left; } - else if (isAccessExpression(node.parent.left)) { - return getElementOrPropertyAccessArgumentExpressionOrName(node.parent.left); + else if (astIsAccessExpression(node.parent.data.left)) { + return astGetElementOrPropertyAccessArgumentExpressionOrName(node.parent.data.left); } } - else if (isVariableDeclaration(node.parent) && isIdentifier(node.parent.name)) { - return node.parent.name; + else if (astIsVariableDeclaration(node.parent) && astIsIdentifier(node.parent.data.name)) { + return node.parent.data.name; } } @@ -1139,16 +1285,16 @@ export function getModifiers(node: HasModifiers): readonly Modifier[] | undefine } } -function getJSDocParameterTagsWorker(param: ParameterDeclaration, noCache?: boolean): readonly JSDocParameterTag[] { - if (param.name) { - if (isIdentifier(param.name)) { - const name = param.name.escapedText; - return getJSDocTagsWorker(param.parent, noCache).filter((tag): tag is JSDocParameterTag => isJSDocParameterTag(tag) && isIdentifier(tag.name) && tag.name.escapedText === name); + function astGetJSDocParameterTagsWorker(param: AstParameterDeclaration, noCache?: boolean): readonly JSDocParameterTag[] { + if (param.data.name) { + if (astIsIdentifier(param.data.name)) { + const name = param.data.name.data.escapedText; + return astGetJSDocTagsWorker(param.parent, noCache).filter((tag): tag is JSDocParameterTag => isJSDocParameterTag(tag) && isIdentifier(tag.name) && tag.name.escapedText === name); } else { - const i = param.parent.parameters.indexOf(param); + const i = param.parent.data.parameters.items.indexOf(param); Debug.assert(i > -1, "Parameters should always be in their parents' parameter list"); - const paramTags = getJSDocTagsWorker(param.parent, noCache).filter(isJSDocParameterTag); + const paramTags = astGetJSDocTagsWorker(param.parent, noCache).filter(isJSDocParameterTag); if (i < paramTags.length) { return [paramTags[i]]; } @@ -1171,17 +1317,38 @@ function getJSDocParameterTagsWorker(param: ParameterDeclaration, noCache?: bool * For binding patterns, parameter tags are matched by position. */ export function getJSDocParameterTags(param: ParameterDeclaration): readonly JSDocParameterTag[] { - return getJSDocParameterTagsWorker(param, /*noCache*/ false); + return astGetJSDocParameterTags(param.ast); +} + +/** + * Gets the JSDoc parameter tags for the node if present. + * + * @remarks Returns any JSDoc param tag whose name matches the provided + * parameter, whether a param tag on a containing function + * expression, or a param tag on a variable declaration whose + * initializer is the containing function. The tags closest to the + * node are returned first, so in the previous example, the param + * tag on the containing function expression would be first. + * + * For binding patterns, parameter tags are matched by position. + */ +export function astGetJSDocParameterTags(param: AstParameterDeclaration): readonly JSDocParameterTag[] { + return astGetJSDocParameterTagsWorker(param, /*noCache*/ false); } /** @internal */ export function getJSDocParameterTagsNoCache(param: ParameterDeclaration): readonly JSDocParameterTag[] { - return getJSDocParameterTagsWorker(param, /*noCache*/ true); + return astGetJSDocParameterTagsNoCache(param.ast); } -function getJSDocTypeParameterTagsWorker(param: TypeParameterDeclaration, noCache?: boolean): readonly JSDocTemplateTag[] { - const name = param.name.escapedText; - return getJSDocTagsWorker(param.parent, noCache).filter((tag): tag is JSDocTemplateTag => isJSDocTemplateTag(tag) && tag.typeParameters.some(tp => tp.name.escapedText === name)); +/** @internal */ +export function astGetJSDocParameterTagsNoCache(param: AstParameterDeclaration): readonly JSDocParameterTag[] { + return astGetJSDocParameterTagsWorker(param, /*noCache*/ true); +} + +function astGetJSDocTypeParameterTagsWorker(param: AstTypeParameterDeclaration, noCache?: boolean): readonly JSDocTemplateTag[] { + const name = param.data.name.data.escapedText; + return astGetJSDocTagsWorker(param.parent, noCache).filter((tag): tag is JSDocTemplateTag => isJSDocTemplateTag(tag) && tag.typeParameters.some(tp => tp.name.escapedText === name)); } /** @@ -1195,12 +1362,31 @@ function getJSDocTypeParameterTagsWorker(param: TypeParameterDeclaration, noCach * tag on the containing function expression would be first. */ export function getJSDocTypeParameterTags(param: TypeParameterDeclaration): readonly JSDocTemplateTag[] { - return getJSDocTypeParameterTagsWorker(param, /*noCache*/ false); + return astGetJSDocTypeParameterTags(param.ast); +} + +/** + * Gets the JSDoc type parameter tags for the node if present. + * + * @remarks Returns any JSDoc template tag whose names match the provided + * parameter, whether a template tag on a containing function + * expression, or a template tag on a variable declaration whose + * initializer is the containing function. The tags closest to the + * node are returned first, so in the previous example, the template + * tag on the containing function expression would be first. + */ +export function astGetJSDocTypeParameterTags(param: AstTypeParameterDeclaration): readonly JSDocTemplateTag[] { + return astGetJSDocTypeParameterTagsWorker(param, /*noCache*/ false); } /** @internal */ export function getJSDocTypeParameterTagsNoCache(param: TypeParameterDeclaration): readonly JSDocTemplateTag[] { - return getJSDocTypeParameterTagsWorker(param, /*noCache*/ true); + return astGetJSDocTypeParameterTagsNoCache(param.ast); +} + +/** @internal */ +export function astGetJSDocTypeParameterTagsNoCache(param: AstTypeParameterDeclaration): readonly JSDocTemplateTag[] { + return astGetJSDocTypeParameterTagsWorker(param, /*noCache*/ true); } /** @@ -1235,7 +1421,12 @@ export function getJSDocPublicTag(node: Node): JSDocPublicTag | undefined { /** @internal */ export function getJSDocPublicTagNoCache(node: Node): JSDocPublicTag | undefined { - return getFirstJSDocTag(node, isJSDocPublicTag, /*noCache*/ true); + return astGetJSDocPublicTagNoCache(node.ast); +} + +/** @internal */ +export function astGetJSDocPublicTagNoCache(node: AstNode): JSDocPublicTag | undefined { + return astGetFirstJSDocTag(node, isJSDocPublicTag, /*noCache*/ true); } /** Gets the JSDoc private tag for the node if present */ @@ -1245,7 +1436,12 @@ export function getJSDocPrivateTag(node: Node): JSDocPrivateTag | undefined { /** @internal */ export function getJSDocPrivateTagNoCache(node: Node): JSDocPrivateTag | undefined { - return getFirstJSDocTag(node, isJSDocPrivateTag, /*noCache*/ true); + return astGetJSDocPrivateTagNoCache(node.ast); +} + +/** @internal */ +export function astGetJSDocPrivateTagNoCache(node: AstNode): JSDocPrivateTag | undefined { + return astGetFirstJSDocTag(node, isJSDocPrivateTag, /*noCache*/ true); } /** Gets the JSDoc protected tag for the node if present */ @@ -1255,7 +1451,12 @@ export function getJSDocProtectedTag(node: Node): JSDocProtectedTag | undefined /** @internal */ export function getJSDocProtectedTagNoCache(node: Node): JSDocProtectedTag | undefined { - return getFirstJSDocTag(node, isJSDocProtectedTag, /*noCache*/ true); + return astGetJSDocProtectedTagNoCache(node.ast); +} + +/** @internal */ +export function astGetJSDocProtectedTagNoCache(node: AstNode): JSDocProtectedTag | undefined { + return astGetFirstJSDocTag(node, isJSDocProtectedTag, /*noCache*/ true); } /** Gets the JSDoc protected tag for the node if present */ @@ -1265,11 +1466,26 @@ export function getJSDocReadonlyTag(node: Node): JSDocReadonlyTag | undefined { /** @internal */ export function getJSDocReadonlyTagNoCache(node: Node): JSDocReadonlyTag | undefined { - return getFirstJSDocTag(node, isJSDocReadonlyTag, /*noCache*/ true); + return astGetJSDocReadonlyTagNoCache(node.ast); } +/** @internal */ +export function astGetJSDocReadonlyTagNoCache(node: AstNode): JSDocReadonlyTag | undefined { + return astGetFirstJSDocTag(node, isJSDocReadonlyTag, /*noCache*/ true); +} + +export function getJSDocOverrideTag(node: Node): JSDocOverrideTag | undefined { + return getFirstJSDocTag(node, isJSDocOverrideTag); +} + +/** @internal */ export function getJSDocOverrideTagNoCache(node: Node): JSDocOverrideTag | undefined { - return getFirstJSDocTag(node, isJSDocOverrideTag, /*noCache*/ true); + return astGetJSDocOverrideTagNoCache(node.ast); +} + +/** @internal */ +export function astGetJSDocOverrideTagNoCache(node: AstNode): JSDocOverrideTag | undefined { + return astGetFirstJSDocTag(node, isJSDocOverrideTag, /*noCache*/ true); } /** Gets the JSDoc deprecated tag for the node if present */ @@ -1279,7 +1495,12 @@ export function getJSDocDeprecatedTag(node: Node): JSDocDeprecatedTag | undefine /** @internal */ export function getJSDocDeprecatedTagNoCache(node: Node): JSDocDeprecatedTag | undefined { - return getFirstJSDocTag(node, isJSDocDeprecatedTag, /*noCache*/ true); + return astGetJSDocDeprecatedTagNoCache(node.ast); +} + +/** @internal */ +export function astGetJSDocDeprecatedTagNoCache(node: AstNode): JSDocDeprecatedTag | undefined { + return astGetFirstJSDocTag(node, isJSDocDeprecatedTag, /*noCache*/ true); } /** Gets the JSDoc enum tag for the node if present */ @@ -1376,6 +1597,22 @@ function getJSDocTagsWorker(node: Node, noCache?: boolean): readonly JSDocTag[] return tags; } +function astGetJSDocTagsWorker(node: AstNode, noCache?: boolean): readonly JSDocTag[] { + if (!astCanHaveJSDoc(node)) return emptyArray; + let tags = node.data.jsDoc?.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 = astGetJSDocCommentsAndTags(node, noCache); + Debug.assert(comments.length < 2 || comments[0] !== comments[1]); + tags = flatMap(comments, j => isJSDoc(j) ? j.tags : j); + if (!noCache) { + node.data.jsDoc ??= []; + node.data.jsDoc.jsDocCache = tags; + } + } + return tags; +} + /** Get all JSDoc tags related to a node, including those on parent nodes. */ export function getJSDocTags(node: Node): readonly JSDocTag[] { return getJSDocTagsWorker(node, /*noCache*/ false); @@ -1383,7 +1620,12 @@ export function getJSDocTags(node: Node): readonly JSDocTag[] { /** Get the first JSDoc tag of a specified kind, or undefined if not present. */ function getFirstJSDocTag(node: Node, predicate: (tag: JSDocTag) => tag is T, noCache?: boolean): T | undefined { - return find(getJSDocTagsWorker(node, noCache), predicate); + return astGetFirstJSDocTag(node.ast, predicate, noCache); +} + +/** Get the first JSDoc tag of a specified kind, or undefined if not present. */ +function astGetFirstJSDocTag(node: AstNode, predicate: (tag: JSDocTag) => tag is T, noCache?: boolean): T | undefined { + return find(astGetJSDocTagsWorker(node, noCache), predicate); } /** Gets all JSDoc tags that match a specified predicate */ @@ -1750,6 +1992,11 @@ export function isClassMemberModifier(idToken: SyntaxKind): boolean { } export function isModifier(node: Node): node is Modifier { + return astIsModifier(node.ast); +} + +/** @internal */ +export function astIsModifier(node: AstNode): node is AstModifier { return isModifierKind(node.kind); } @@ -1781,9 +2028,17 @@ export function isFunctionLike(node: Node | undefined): node is SignatureDeclara return !!node && isFunctionLikeKind(node.kind); } -/** @internal */ +/** + * @deprecated Use {@link astIsFunctionLikeOrClassStaticBlockDeclaration} + * @internal + */ export function isFunctionLikeOrClassStaticBlockDeclaration(node: Node | undefined): node is SignatureDeclaration | ClassStaticBlockDeclaration { - return !!node && (isFunctionLikeKind(node.kind) || isClassStaticBlockDeclaration(node)); + return astIsFunctionLikeOrClassStaticBlockDeclaration(node?.ast); +} + +/** @internal */ +export function astIsFunctionLikeOrClassStaticBlockDeclaration(node: AstNode | undefined): node is AstSignatureDeclaration | AstClassStaticBlockDeclaration { + return !!node && (isFunctionLikeKind(node.kind) || astIsClassStaticBlockDeclaration(node)); } /** @internal */ @@ -1835,6 +2090,11 @@ export function isFunctionOrModuleBlock(node: Node): boolean { // Classes export function isClassElement(node: Node): node is ClassElement { + return astIsClassElement(node.ast); +} + +// Classes +export function astIsClassElement(node: AstNode): node is AstClassElement { const kind = node.kind; return kind === SyntaxKind.Constructor || kind === SyntaxKind.PropertyDeclaration @@ -1847,6 +2107,10 @@ export function isClassElement(node: Node): node is ClassElement { } export function isClassLike(node: Node): node is ClassLikeDeclaration { + return node && astIsClassLike(node.ast); +} + +export function astIsClassLike(node: AstNode): node is AstClassLikeDeclaration { return node && (node.kind === SyntaxKind.ClassDeclaration || node.kind === SyntaxKind.ClassExpression); } @@ -1858,6 +2122,11 @@ export function isAutoAccessorPropertyDeclaration(node: Node): node is AutoAcces return isPropertyDeclaration(node) && hasAccessorModifier(node); } +/** @internal */ +export function astIsAutoAccessorPropertyDeclaration(node: AstNode): node is AstAutoAccessorPropertyDeclaration { + return astIsPropertyDeclaration(node) && astHasAccessorModifier(node); +} + /** @internal */ export function isClassInstanceProperty(node: Declaration): boolean { if (isInJSFile(node) && isExpandoPropertyDeclaration(node)) { @@ -1881,7 +2150,12 @@ export function isMethodOrAccessor(node: Node): node is MethodDeclaration | Acce // Type members export function isModifierLike(node: Node): node is ModifierLike { - return isModifier(node) || isDecorator(node); + return astIsModifierLike(node.ast); +} + +/** @intenral */ +export function astIsModifierLike(node: AstNode): node is AstModifierLike { + return astIsModifier(node) || astIsDecorator(node); } export function isTypeElement(node: Node): node is TypeElement { @@ -1933,8 +2207,13 @@ export function isFunctionOrConstructorTypeNode(node: Node): node is FunctionTyp // Binding patterns -/** @internal */ +/** @deprecated @internal */ export function isBindingPattern(node: Node | undefined): node is BindingPattern { + return astIsBindingPattern(node?.ast); +} + +/** @internal */ +export function astIsBindingPattern(node: AstNode | undefined): node is AstBindingPattern { if (node) { const kind = node.kind; return kind === SyntaxKind.ArrayBindingPattern @@ -2194,7 +2473,8 @@ export function isExpression(node: Node): node is Expression { return isExpressionKind(skipPartiallyEmittedExpressions(node).kind); } -function isExpressionKind(kind: SyntaxKind): boolean { +/** @internal */ +export function isExpressionKind(kind: SyntaxKind): boolean { switch (kind) { case SyntaxKind.ConditionalExpression: case SyntaxKind.YieldExpression: @@ -2503,8 +2783,13 @@ function isStatementKindButNotDeclarationKind(kind: SyntaxKind) { /** @internal */ export function isDeclaration(node: Node): node is NamedDeclaration { + return astIsDeclaration(node.ast); +} + +/** @internal */ +export function astIsDeclaration(node: AstNode): node is AstNamedDeclaration { if (node.kind === SyntaxKind.TypeParameter) { - return (node.parent && node.parent.kind !== SyntaxKind.JSDocTemplateTag) || isInJSFile(node); + return (node.parent && node.parent.kind !== SyntaxKind.JSDocTemplateTag) || astIsInJSFile(node); } return isDeclarationKind(node.kind); @@ -2625,6 +2910,15 @@ export function isJSDocNode(node: Node): boolean { return node.kind >= SyntaxKind.FirstJSDocNode && node.kind <= SyntaxKind.LastJSDocNode; } +/** + * True if node is of some JSDoc syntax kind. + * + * @internal + */ +export function astIsJSDocNode(node: AstNode): boolean { + return node.kind >= SyntaxKind.FirstJSDocNode && node.kind <= SyntaxKind.LastJSDocNode; +} + /** True if node is of a kind that may contain comment text. */ export function isJSDocCommentContainingNode(node: Node): boolean { return node.kind === SyntaxKind.JSDoc diff --git a/src/compiler/visitorPublic.ts b/src/compiler/visitorPublic.ts index dbd49379e57..82cfd149537 100644 --- a/src/compiler/visitorPublic.ts +++ b/src/compiler/visitorPublic.ts @@ -13,7 +13,7 @@ import { isArrayBindingElement, isAssertClause, isAssertsKeyword, - isAsteriskToken, + astIseriskToken, isAwaitKeyword, isBinaryOperatorToken, isBindingElement, @@ -705,7 +705,7 @@ const visitEachChildTable: VisitEachChildTable = { return context.factory.updateMethodDeclaration( node, nodesVisitor(node.modifiers, visitor, isModifierLike), - tokenVisitor ? nodeVisitor(node.asteriskToken, tokenVisitor, isAsteriskToken) : node.asteriskToken, + tokenVisitor ? nodeVisitor(node.asteriskToken, tokenVisitor, astIseriskToken) : node.asteriskToken, Debug.checkDefined(nodeVisitor(node.name, visitor, isPropertyName)), tokenVisitor ? nodeVisitor(node.questionToken, tokenVisitor, isQuestionToken) : node.questionToken, nodesVisitor(node.typeParameters, visitor, isTypeParameterDeclaration), @@ -1102,7 +1102,7 @@ const visitEachChildTable: VisitEachChildTable = { return context.factory.updateFunctionExpression( node, nodesVisitor(node.modifiers, visitor, isModifier), - tokenVisitor ? nodeVisitor(node.asteriskToken, tokenVisitor, isAsteriskToken) : node.asteriskToken, + tokenVisitor ? nodeVisitor(node.asteriskToken, tokenVisitor, astIseriskToken) : node.asteriskToken, nodeVisitor(node.name, visitor, isIdentifier), nodesVisitor(node.typeParameters, visitor, isTypeParameterDeclaration), visitParameterList(node.parameters, visitor, context, nodesVisitor), @@ -1196,7 +1196,7 @@ const visitEachChildTable: VisitEachChildTable = { [SyntaxKind.YieldExpression]: function visitEachChildOfYieldExpression(node, visitor, context, _nodesVisitor, nodeVisitor, tokenVisitor) { return context.factory.updateYieldExpression( node, - tokenVisitor ? nodeVisitor(node.asteriskToken, tokenVisitor, isAsteriskToken) : node.asteriskToken, + tokenVisitor ? nodeVisitor(node.asteriskToken, tokenVisitor, astIseriskToken) : node.asteriskToken, nodeVisitor(node.expression, visitor, isExpression), ); }, @@ -1430,7 +1430,7 @@ const visitEachChildTable: VisitEachChildTable = { return context.factory.updateFunctionDeclaration( node, nodesVisitor(node.modifiers, visitor, isModifier), - tokenVisitor ? nodeVisitor(node.asteriskToken, tokenVisitor, isAsteriskToken) : node.asteriskToken, + tokenVisitor ? nodeVisitor(node.asteriskToken, tokenVisitor, astIseriskToken) : node.asteriskToken, nodeVisitor(node.name, visitor, isIdentifier), nodesVisitor(node.typeParameters, visitor, isTypeParameterDeclaration), visitParameterList(node.parameters, visitor, context, nodesVisitor), diff --git a/src/services/jsDoc.ts b/src/services/jsDoc.ts index 0f8cb859d68..c6e93032c85 100644 --- a/src/services/jsDoc.ts +++ b/src/services/jsDoc.ts @@ -244,7 +244,7 @@ function getCommentHavingNodes(declaration: Declaration): readonly (JSDoc | JSDo } /** @internal */ -export function getJsDocTagsFromDeclarations(declarations?: Declaration[], checker?: TypeChecker): JSDocTagInfo[] { +export function getJsDocTagsFromDeclarations(declarations?: readonly Declaration[], checker?: TypeChecker): JSDocTagInfo[] { // Only collect doc comments from duplicate declarations once. const infos: JSDocTagInfo[] = []; forEachUnique(declarations, declaration => { diff --git a/src/services/services.ts b/src/services/services.ts index 6a8531f7dcd..7621fec5047 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -299,6 +299,8 @@ import { UnionType, updateSourceFile, UserPreferences, + AstDeclaration, + createReadOnlyArrayView, } from "./_namespaces/ts.js"; import * as NavigateTo from "./_namespaces/ts.NavigateTo.js"; import * as NavigationBar from "./_namespaces/ts.NavigationBar.js"; @@ -316,8 +318,9 @@ export const servicesVersion = "0.8"; class SymbolObject implements Symbol { flags: SymbolFlags; escapedName: __String; - declarations?: Declaration[]; - valueDeclaration?: Declaration; + private _declarations: readonly Declaration[] | undefined = undefined; + astValueDeclaration: AstDeclaration | undefined = undefined; + astDeclarations: AstDeclaration[] | undefined = undefined; members?: SymbolTable; exports?: SymbolTable; id: number; @@ -344,8 +347,6 @@ class SymbolObject implements Symbol { // Note: if modifying this, be sure to update Symbol in src/compiler/types.ts this.flags = flags; this.escapedName = name; - this.declarations = undefined; - this.valueDeclaration = undefined; this.id = 0; this.mergeId = 0; this.parent = undefined; @@ -358,6 +359,10 @@ class SymbolObject implements Symbol { this.links = undefined; // used by TransientSymbol } + get valueDeclaration() { return this.astValueDeclaration?.node; } + set valueDeclaration(value) { this.astValueDeclaration = value?.ast; } + get declarations() { return this._declarations ??= this.astDeclarations && createReadOnlyArrayView(this.astDeclarations, ast => ast.node); } + getFlags(): SymbolFlags { return this.flags; } @@ -374,7 +379,7 @@ class SymbolObject implements Symbol { return this.name; } - getDeclarations(): Declaration[] | undefined { + getDeclarations(): readonly Declaration[] | undefined { return this.declarations; } @@ -617,7 +622,7 @@ function hasJSDocInheritDocTag(node: Node) { return getJSDocTags(node).some(tag => tag.tagName.text === "inheritDoc" || tag.tagName.text === "inheritdoc"); } -function getJsDocTagsOfDeclarations(declarations: Declaration[] | undefined, checker: TypeChecker | undefined): JSDocTagInfo[] { +function getJsDocTagsOfDeclarations(declarations: readonly Declaration[] | undefined, checker: TypeChecker | undefined): JSDocTagInfo[] { if (!declarations) return emptyArray; let tags = JsDoc.getJsDocTagsFromDeclarations(declarations, checker); diff --git a/src/services/types.ts b/src/services/types.ts index f15fb1cfcb1..5d9573421c7 100644 --- a/src/services/types.ts +++ b/src/services/types.ts @@ -51,7 +51,7 @@ declare module "../compiler/types.js" { getFlags(): SymbolFlags; getEscapedName(): __String; getName(): string; - getDeclarations(): Declaration[] | undefined; + getDeclarations(): readonly Declaration[] | undefined; getDocumentationComment(typeChecker: TypeChecker | undefined): SymbolDisplayPart[]; /** @internal */ getContextualDocumentationComment(context: Node | undefined, checker: TypeChecker | undefined): SymbolDisplayPart[]; diff --git a/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.@link tags.json b/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.@link tags.json index 0b04453b8c8..d0c11175d89 100644 --- a/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.@link tags.json +++ b/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.@link tags.json @@ -5,7 +5,7 @@ "flags": "JSDoc", "modifierFlagsCache": 0, "transformFlags": 0, - "comment": { + "commentArray": { "0": { "kind": "JSDocText", "pos": 0, @@ -89,7 +89,7 @@ "transformFlags": 0, "escapedText": "param" }, - "comment": { + "commentArray": { "0": { "kind": "JSDocText", "pos": 70, @@ -164,7 +164,7 @@ "transformFlags": 0, "escapedText": "param" }, - "comment": { + "commentArray": { "0": { "kind": "JSDocText", "pos": 113, @@ -404,7 +404,7 @@ "transformFlags": 0, "escapedText": "author" }, - "comment": { + "commentArray": { "0": { "kind": "JSDocText", "pos": 597, diff --git a/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.authorTag.json b/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.authorTag.json index ff56dc4ecb8..bb4bc51e36c 100644 --- a/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.authorTag.json +++ b/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.authorTag.json @@ -21,7 +21,7 @@ "transformFlags": 0, "escapedText": "author" }, - "comment": { + "commentArray": { "0": { "kind": "JSDocText", "pos": 15, @@ -87,7 +87,7 @@ "transformFlags": 0, "escapedText": "author" }, - "comment": { + "commentArray": { "0": { "kind": "JSDocText", "pos": 178, @@ -119,7 +119,7 @@ "transformFlags": 0, "escapedText": "author" }, - "comment": { + "commentArray": { "0": { "kind": "JSDocText", "pos": 235, @@ -168,7 +168,7 @@ "transformFlags": 0, "escapedText": "author" }, - "comment": { + "commentArray": { "0": { "kind": "JSDocText", "pos": 346, @@ -200,7 +200,7 @@ "transformFlags": 0, "escapedText": "author" }, - "comment": { + "commentArray": { "0": { "kind": "JSDocText", "pos": 389, @@ -232,7 +232,7 @@ "transformFlags": 0, "escapedText": "author" }, - "comment": { + "commentArray": { "0": { "kind": "JSDocText", "pos": 406, @@ -264,7 +264,7 @@ "transformFlags": 0, "escapedText": "author" }, - "comment": { + "commentArray": { "0": { "kind": "JSDocText", "pos": 437, @@ -296,7 +296,7 @@ "transformFlags": 0, "escapedText": "author" }, - "comment": { + "commentArray": { "0": { "kind": "JSDocText", "pos": 453, @@ -328,7 +328,7 @@ "transformFlags": 0, "escapedText": "author" }, - "comment": { + "commentArray": { "0": { "kind": "JSDocText", "pos": 461, @@ -360,7 +360,7 @@ "transformFlags": 0, "escapedText": "author" }, - "comment": { + "commentArray": { "0": { "kind": "JSDocText", "pos": 469, @@ -392,7 +392,7 @@ "transformFlags": 0, "escapedText": "author" }, - "comment": { + "commentArray": { "0": { "kind": "JSDocText", "pos": 497, @@ -424,7 +424,7 @@ "transformFlags": 0, "escapedText": "author" }, - "comment": { + "commentArray": { "0": { "kind": "JSDocText", "pos": 510, @@ -456,7 +456,7 @@ "transformFlags": 0, "escapedText": "author" }, - "comment": { + "commentArray": { "0": { "kind": "JSDocText", "pos": 530, diff --git a/tests/baselines/reference/api/typescript.d.ts b/tests/baselines/reference/api/typescript.d.ts index 436b60f503d..f9d15c66f73 100644 --- a/tests/baselines/reference/api/typescript.d.ts +++ b/tests/baselines/reference/api/typescript.d.ts @@ -4444,10 +4444,10 @@ declare namespace ts { | ModuleBlock | MissingDeclaration | NotEmittedStatement; - export type HasType = SignatureDeclaration | VariableDeclaration | ParameterDeclaration | PropertySignature | PropertyDeclaration | TypePredicateNode | ParenthesizedTypeNode | TypeOperatorNode | MappedTypeNode | AssertionExpression | TypeAliasDeclaration | JSDocTypeExpression | JSDocNonNullableType | JSDocNullableType | JSDocOptionalType | JSDocVariadicType; - export type HasTypeArguments = CallExpression | NewExpression | TaggedTemplateExpression | JsxOpeningElement | JsxSelfClosingElement; + export type HasType = SignatureDeclaration | VariableDeclaration | ParameterDeclaration | PropertySignature | PropertyDeclaration | TypePredicateNode | ParenthesizedTypeNode | TypeOperatorNode | MappedTypeNode | AssertionExpression | TypeAliasDeclaration | JSDocTypeExpression | JSDocNonNullableType | JSDocNullableType | JSDocOptionalType | JSDocVariadicType | OptionalTypeNode | RestTypeNode | NamedTupleMember | TemplateLiteralTypeSpan | SatisfiesExpression | JSDocNamepathType | JSDocSignature; + export type HasTypeArguments = CallExpression | NewExpression | TaggedTemplateExpression | ExpressionWithTypeArguments | TypeQueryNode | ImportTypeNode | TypeReferenceNode | JsxOpeningElement | JsxSelfClosingElement; export type HasInitializer = HasExpressionInitializer | ForStatement | ForInStatement | ForOfStatement | JsxAttribute; - export type HasExpressionInitializer = VariableDeclaration | ParameterDeclaration | BindingElement | PropertyDeclaration | PropertyAssignment | EnumMember; + export type HasExpressionInitializer = VariableDeclaration | ParameterDeclaration | BindingElement | PropertyDeclaration | PropertyAssignment | PropertySignature | EnumMember; export type HasDecorators = ParameterDeclaration | PropertyDeclaration | MethodDeclaration | GetAccessorDeclaration | SetAccessorDeclaration | ClassExpression | ClassDeclaration; export type HasModifiers = TypeParameterDeclaration | ParameterDeclaration | ConstructorTypeNode | PropertySignature | PropertyDeclaration | MethodSignature | MethodDeclaration | ConstructorDeclaration | GetAccessorDeclaration | SetAccessorDeclaration | IndexSignatureDeclaration | FunctionExpression | ArrowFunction | ClassExpression | VariableStatement | FunctionDeclaration | ClassDeclaration | InterfaceDeclaration | TypeAliasDeclaration | EnumDeclaration | ModuleDeclaration | ImportEqualsDeclaration | ImportDeclaration | ExportAssignment | ExportDeclaration; export class NodeArray extends ReadonlyArray { @@ -5239,10 +5239,14 @@ declare namespace ts { get right(): Expression; } export type AssignmentOperatorToken = Token; - export interface AssignmentExpression extends BinaryExpression { + export type AssignmentExpression = BinaryExpression & { readonly left: LeftHandSideExpression; readonly operatorToken: TOperator; - } + readonly data: { + readonly left: AstLeftHandSideExpression; + readonly operatorToken: TOperator; + }; + }; export interface ObjectDestructuringAssignment extends AssignmentExpression { readonly left: ObjectLiteralExpression; } @@ -5586,7 +5590,7 @@ declare namespace ts { get expression(): Expression; get type(): TypeNode; } - export class TypeAssertionExpression extends Node implements UnaryExpression { + export class TypeAssertionExpression extends Node implements UnaryExpression { _unaryExpressionBrand: any; _expressionBrand: any; get type(): TypeNode; @@ -6417,13 +6421,18 @@ declare namespace ts { get type(): JSDocReturnTag | undefined; } export interface JSDocPropertyLikeTag extends JSDocTag, Declaration { - readonly data: AstJSDocTagData & AstDeclarationData; readonly parent: JSDoc; readonly name: EntityName; readonly typeExpression?: JSDocTypeExpression | undefined; /** Whether the property name came before the type -- non-standard for JSDoc, but Typescript-like */ readonly isNameFirst: boolean; readonly isBracketed: boolean; + readonly data: AstJSDocTagData & AstDeclarationData & { + readonly name: AstEntityName; + readonly typeExpression?: AstJSDocTypeExpression | undefined; + readonly isNameFirst: boolean; + readonly isBracketed: boolean; + }; } export class JSDocPropertyTag extends JSDocTag implements JSDocPropertyLikeTag, Declaration { _declarationBrand: any; @@ -7126,8 +7135,8 @@ declare namespace ts { export interface Symbol { flags: SymbolFlags; escapedName: __String; - declarations?: Declaration[]; - valueDeclaration?: Declaration; + readonly declarations?: readonly Declaration[]; + readonly valueDeclaration?: Declaration; members?: SymbolTable; exports?: SymbolTable; globalExports?: SymbolTable; @@ -7137,7 +7146,7 @@ declare namespace ts { getFlags(): SymbolFlags; getEscapedName(): __String; getName(): string; - getDeclarations(): Declaration[] | undefined; + getDeclarations(): readonly Declaration[] | undefined; getDocumentationComment(typeChecker: TypeChecker | undefined): SymbolDisplayPart[]; getJsDocTags(checker?: TypeChecker): JSDocTagInfo[]; } @@ -9024,7 +9033,7 @@ declare namespace ts { private _extra; readonly kind: N["kind"]; readonly data: N["data"]; - parent: AstNode> | undefined; + parent: AstNodeOneOf; flags: NodeFlags; pos: number; end: number; @@ -9405,6 +9414,7 @@ declare namespace ts { type: AstTypeNode | undefined; initializer: AstExpression | undefined; } + export type AstVariableLikeDeclaration = AstNodeOneOf; export type AstVariableDeclarationList = AstNode; export class AstVariableDeclarationListData extends AstData { declarations: AstNodeArray; @@ -9417,6 +9427,7 @@ declare namespace ts { initializer: AstExpression | undefined; } export type AstPropertyDeclaration = AstNode; + export type AstAutoAccessorPropertyDeclaration = AstNode; export class AstPropertyDeclarationData extends AstData { modifiers: AstNodeArray | undefined; name: AstPropertyName; @@ -9669,6 +9680,7 @@ declare namespace ts { operatorToken: AstBinaryOperatorToken; right: AstExpression; } + export type AstAssignmentExpression = AstNodeOneOf>; export type AstDestructuringAssignment = AstNodeOneOf; export class AstConditionalExpressionData extends AstData { condition: AstExpression; @@ -9771,6 +9783,7 @@ declare namespace ts { name: AstMemberName; } export type AstPropertyAccessEntityNameExpression = AstNode; + export type AstAccessExpression = AstNodeOneOf; export type AstEntityNameExpression = AstNodeOneOf; export type AstPropertyAccessChain = AstNode; export class AstElementAccessExpressionData extends AstData { @@ -9806,7 +9819,7 @@ declare namespace ts { expression: AstExpression; type: AstTypeNode; } - export class AstTypeAssertionData extends AstData { + export class AstTypeAssertionExpressionData extends AstData { type: AstTypeNode; expression: AstUnaryExpression; } @@ -10164,7 +10177,8 @@ declare namespace ts { type: AstTypeNode; } export class AstJSDocData extends AstData { - comment: string | AstNodeArray | undefined; + comment: string | undefined; + commentArray: AstNodeArray | undefined; tags: AstNodeArray | undefined; } export type AstHasJSDoc = AstNodeOneOf; @@ -10186,71 +10200,135 @@ declare namespace ts { text: string; } export type AstBaseJSDocTag = AstNode>; - export class AstJSDocTagData extends AstData { - tagName: AstIdentifier; - comment: string | AstNodeArray | undefined; + export abstract class AstJSDocTagData extends AstData { + abstract tagName: AstIdentifier; + abstract comment: string | undefined; + abstract commentArray: AstNodeArray | undefined; } export class AstJSDocUnknownTagData extends AstJSDocTagData { + tagName: AstIdentifier; + comment: string | undefined; + commentArray: AstNodeArray | undefined; } export type AstJSDocClassReference = AstNode; export interface AstJSDocClassReferenceData extends AstExpressionWithTypeArgumentsData { expression: AstIdentifier | AstPropertyAccessEntityNameExpression; } export class AstJSDocAugmentsTagData extends AstJSDocTagData { + tagName: AstIdentifier; + comment: string | undefined; + commentArray: AstNodeArray | undefined; class: AstJSDocClassReference; } export class AstJSDocImplementsTagData extends AstJSDocTagData { + tagName: AstIdentifier; + comment: string | undefined; + commentArray: AstNodeArray | undefined; class: AstJSDocClassReference; } export class AstJSDocAuthorTagData extends AstJSDocTagData { + tagName: AstIdentifier; + comment: string | undefined; + commentArray: AstNodeArray | undefined; } export class AstJSDocDeprecatedTagData extends AstJSDocTagData { + tagName: AstIdentifier; + comment: string | undefined; + commentArray: AstNodeArray | undefined; } export class AstJSDocClassTagData extends AstJSDocTagData { + tagName: AstIdentifier; + comment: string | undefined; + commentArray: AstNodeArray | undefined; } export class AstJSDocPublicTagData extends AstJSDocTagData { + tagName: AstIdentifier; + comment: string | undefined; + commentArray: AstNodeArray | undefined; } export class AstJSDocPrivateTagData extends AstJSDocTagData { + tagName: AstIdentifier; + comment: string | undefined; + commentArray: AstNodeArray | undefined; } export class AstJSDocProtectedTagData extends AstJSDocTagData { + tagName: AstIdentifier; + comment: string | undefined; + commentArray: AstNodeArray | undefined; } export class AstJSDocReadonlyTagData extends AstJSDocTagData { + tagName: AstIdentifier; + comment: string | undefined; + commentArray: AstNodeArray | undefined; } export class AstJSDocOverrideTagData extends AstJSDocTagData { + tagName: AstIdentifier; + comment: string | undefined; + commentArray: AstNodeArray | undefined; } export class AstJSDocEnumTagData extends AstJSDocTagData { + tagName: AstIdentifier; + comment: string | undefined; + commentArray: AstNodeArray | undefined; typeExpression: AstJSDocTypeExpression; } export class AstJSDocThisTagData extends AstJSDocTagData { + tagName: AstIdentifier; + comment: string | undefined; + commentArray: AstNodeArray | undefined; typeExpression: AstJSDocTypeExpression; } export class AstJSDocTemplateTagData extends AstJSDocTagData { + tagName: AstIdentifier; + comment: string | undefined; + commentArray: AstNodeArray | undefined; constraint: AstJSDocTypeExpression | undefined; typeParameters: AstNodeArray; } export class AstJSDocSeeTagData extends AstJSDocTagData { + tagName: AstIdentifier; + comment: string | undefined; + commentArray: AstNodeArray | undefined; name: AstJSDocNameReference | undefined; } export class AstJSDocReturnTagData extends AstJSDocTagData { + tagName: AstIdentifier; + comment: string | undefined; + commentArray: AstNodeArray | undefined; typeExpression: AstJSDocTypeExpression | undefined; } export class AstJSDocTypeTagData extends AstJSDocTagData { + tagName: AstIdentifier; + comment: string | undefined; + commentArray: AstNodeArray | undefined; typeExpression: AstJSDocTypeExpression; } export class AstJSDocTypedefTagData extends AstJSDocTagData { + tagName: AstIdentifier; + comment: string | undefined; + commentArray: AstNodeArray | undefined; typeExpression: AstJSDocTypeExpression | AstJSDocTypeLiteral | undefined; fullName: AstJSDocNamespaceDeclaration | AstIdentifier | undefined; name: AstIdentifier | undefined; } export class AstJSDocCallbackTagData extends AstJSDocTagData { + tagName: AstIdentifier; + comment: string | undefined; + commentArray: AstNodeArray | undefined; fullName: AstJSDocNamespaceDeclaration | AstIdentifier | undefined; name: AstIdentifier | undefined; typeExpression: AstJSDocSignature; } export class AstJSDocOverloadTagData extends AstJSDocTagData { + tagName: AstIdentifier; + comment: string | undefined; + commentArray: AstNodeArray | undefined; typeExpression: AstJSDocSignature; } export class AstJSDocThrowsTagData extends AstJSDocTagData { + tagName: AstIdentifier; + comment: string | undefined; + commentArray: AstNodeArray | undefined; typeExpression: AstJSDocTypeExpression | undefined; } export class AstJSDocSignatureData extends AstData { @@ -10259,6 +10337,9 @@ declare namespace ts { type: AstJSDocReturnTag | undefined; } export class AstJSDocPropertyTagData extends AstJSDocTagData { + tagName: AstIdentifier; + comment: string | undefined; + commentArray: AstNodeArray | undefined; typeExpression: AstJSDocTypeExpression | undefined; name: AstEntityName; /** Whether the property name came before the type -- non-standard for JSDoc, but Typescript-like */ @@ -10266,6 +10347,9 @@ declare namespace ts { isBracketed: boolean; } export class AstJSDocParameterTagData extends AstJSDocTagData { + tagName: AstIdentifier; + comment: string | undefined; + commentArray: AstNodeArray | undefined; typeExpression: AstJSDocTypeExpression | undefined; name: AstEntityName; /** Whether the property name came before the type -- non-standard for JSDoc, but Typescript-like */ @@ -10279,9 +10363,15 @@ declare namespace ts { isArrayType: boolean; } export class AstJSDocSatisfiesTagData extends AstJSDocTagData { + tagName: AstIdentifier; + comment: string | undefined; + commentArray: AstNodeArray | undefined; typeExpression: AstJSDocTypeExpression; } export class AstJSDocImportTagData extends AstJSDocTagData { + tagName: AstIdentifier; + comment: string | undefined; + commentArray: AstNodeArray | undefined; importClause: AstImportClause | undefined; moduleSpecifier: AstExpression; attributes: AstImportAttributes | undefined; @@ -10350,7 +10440,6 @@ declare namespace ts { impliedNodeFormat: ResolutionMode | undefined; moduleName: string | undefined; namedDeclarations: Map | undefined; - cloneNode(node: AstNode): AstNode; } export type AstMethodSignature = AstNode; export type AstMethodDeclaration = AstNode; @@ -10587,6 +10676,7 @@ declare namespace ts { > > : never; + export type AstNamedDeclaration = AstNodeOneOf; export enum FileWatcherEventKind { Created = 0, Changed = 1, @@ -10801,14 +10891,22 @@ declare namespace ts { */ export function unescapeLeadingUnderscores(identifier: __String): string; export function idText(identifierOrPrivateName: Identifier | PrivateIdentifier): string; + export function astIdText(identifierOrPrivateName: AstIdentifier | AstPrivateIdentifier): string; /** * If the text of an Identifier matches a keyword (including contextual and TypeScript-specific keywords), returns the * SyntaxKind for the matching keyword. */ export function identifierToKeywordKind(node: Identifier): KeywordSyntaxKind | undefined; + /** + * If the text of an Identifier matches a keyword (including contextual and TypeScript-specific keywords), returns the + * SyntaxKind for the matching keyword. + */ + export function astIdentifierToKeywordKind(node: AstIdentifier): KeywordSyntaxKind | undefined; export function symbolName(symbol: Symbol): string; export function getNameOfJSDocTypedef(declaration: JSDocTypedefTag): Identifier | PrivateIdentifier | undefined; + export function astGetNameOfJSDocTypedef(declaration: AstJSDocTypedefTag): AstIdentifier | AstPrivateIdentifier | undefined; export function getNameOfDeclaration(declaration: Declaration | Expression | undefined): DeclarationName | undefined; + export function astGetNameOfDeclaration(declaration: AstDeclaration | AstExpression | undefined): AstDeclarationName | undefined; export function getDecorators(node: HasDecorators): readonly Decorator[] | undefined; export function getModifiers(node: HasModifiers): readonly Modifier[] | undefined; /** @@ -10824,6 +10922,19 @@ declare namespace ts { * For binding patterns, parameter tags are matched by position. */ export function getJSDocParameterTags(param: ParameterDeclaration): readonly JSDocParameterTag[]; + /** + * Gets the JSDoc parameter tags for the node if present. + * + * @remarks Returns any JSDoc param tag whose name matches the provided + * parameter, whether a param tag on a containing function + * expression, or a param tag on a variable declaration whose + * initializer is the containing function. The tags closest to the + * node are returned first, so in the previous example, the param + * tag on the containing function expression would be first. + * + * For binding patterns, parameter tags are matched by position. + */ + export function astGetJSDocParameterTags(param: AstParameterDeclaration): readonly JSDocParameterTag[]; /** * Gets the JSDoc type parameter tags for the node if present. * @@ -10835,6 +10946,17 @@ declare namespace ts { * tag on the containing function expression would be first. */ export function getJSDocTypeParameterTags(param: TypeParameterDeclaration): readonly JSDocTemplateTag[]; + /** + * Gets the JSDoc type parameter tags for the node if present. + * + * @remarks Returns any JSDoc template tag whose names match the provided + * parameter, whether a template tag on a containing function + * expression, or a template tag on a variable declaration whose + * initializer is the containing function. The tags closest to the + * node are returned first, so in the previous example, the template + * tag on the containing function expression would be first. + */ + export function astGetJSDocTypeParameterTags(param: AstTypeParameterDeclaration): readonly JSDocTemplateTag[]; /** * Return true if the node has JSDoc parameter tags. * @@ -10856,7 +10978,7 @@ declare namespace ts { export function getJSDocProtectedTag(node: Node): JSDocProtectedTag | undefined; /** Gets the JSDoc protected tag for the node if present */ export function getJSDocReadonlyTag(node: Node): JSDocReadonlyTag | undefined; - export function getJSDocOverrideTagNoCache(node: Node): JSDocOverrideTag | undefined; + export function getJSDocOverrideTag(node: Node): JSDocOverrideTag | undefined; /** Gets the JSDoc deprecated tag for the node if present */ export function getJSDocDeprecatedTag(node: Node): JSDocDeprecatedTag | undefined; /** Gets the JSDoc enum tag for the node if present */ @@ -10950,10 +11072,14 @@ declare namespace ts { export function isBindingName(node: Node): node is BindingName; export function isFunctionLike(node: Node | undefined): node is SignatureDeclaration; export function isClassElement(node: Node): node is ClassElement; + export function astIsClassElement(node: AstNode): node is AstClassElement; export function isClassLike(node: Node): node is ClassLikeDeclaration; + export function astIsClassLike(node: AstNode): node is AstClassLikeDeclaration; export function isAccessor(node: Node): node is AccessorDeclaration; export function isAutoAccessorPropertyDeclaration(node: Node): node is AutoAccessorPropertyDeclaration; export function isModifierLike(node: Node): node is ModifierLike; + /** @intenral */ + export function astIsModifierLike(node: AstNode): node is AstModifierLike; export function isTypeElement(node: Node): node is TypeElement; export function isClassOrTypeElement(node: Node): node is ClassElement | TypeElement; export function isObjectLiteralElementLike(node: Node): node is ObjectLiteralElementLike; @@ -11030,6 +11156,26 @@ declare namespace ts { * ``` */ export function getJSDocCommentsAndTags(hostNode: Node): readonly (JSDoc | JSDocTag)[]; + /** + * This function checks multiple locations for JSDoc comments that apply to a host node. + * At each location, the whole comment may apply to the node, or only a specific tag in + * the comment. In the first case, location adds the entire {@link JSDoc} object. In the + * second case, it adds the applicable {@link JSDocTag}. + * + * For example, a JSDoc comment before a parameter adds the entire {@link JSDoc}. But a + * `@param` tag on the parent function only adds the {@link JSDocTag} for the `@param`. + * + * ```ts + * /** JSDoc will be returned for `a` *\/ + * const a = 0 + * /** + * * Entire JSDoc will be returned for `b` + * * @param c JSDocTag will be returned for `c` + * *\/ + * function b(/** JSDoc will be returned for `c` *\/ c) {} + * ``` + */ + export function astGetJSDocCommentsAndTags(hostNode: AstNode): readonly (JSDoc | JSDocTag)[]; /** * Create an external source map source file reference */ @@ -11116,7 +11262,7 @@ declare namespace ts { export function isDotDotDotToken(node: Node): node is DotDotDotToken; export function isPlusToken(node: Node): node is PlusToken; export function isMinusToken(node: Node): node is MinusToken; - export function isAsteriskToken(node: Node): node is AsteriskToken; + export function astIseriskToken(node: Node): node is AsteriskToken; export function isExclamationToken(node: Node): node is ExclamationToken; export function isQuestionToken(node: Node): node is QuestionToken; export function isColonToken(node: Node): node is ColonToken; diff --git a/tests/baselines/reference/skipJSDocParsing/link-ParseForTypeInfo-file.ts.diff b/tests/baselines/reference/skipJSDocParsing/link-ParseForTypeInfo-file.ts.diff index 124598753a8..be7f858ee0c 100644 --- a/tests/baselines/reference/skipJSDocParsing/link-ParseForTypeInfo-file.ts.diff +++ b/tests/baselines/reference/skipJSDocParsing/link-ParseForTypeInfo-file.ts.diff @@ -15,7 +15,7 @@ - "flags": "JSDoc", - "modifierFlagsCache": 0, - "transformFlags": 0, -- "comment": { +- "commentArray": { - "0": { - "kind": "JSDocText", - "pos": 32, diff --git a/tests/baselines/reference/skipJSDocParsing/link-ParseNone-file.js.diff b/tests/baselines/reference/skipJSDocParsing/link-ParseNone-file.js.diff index 41a1390a61b..8bd36ef0ca1 100644 --- a/tests/baselines/reference/skipJSDocParsing/link-ParseNone-file.js.diff +++ b/tests/baselines/reference/skipJSDocParsing/link-ParseNone-file.js.diff @@ -15,7 +15,7 @@ - "flags": "JSDoc", - "modifierFlagsCache": 0, - "transformFlags": 0, -- "comment": { +- "commentArray": { - "0": { - "kind": "JSDocText", - "pos": 32, diff --git a/tests/baselines/reference/skipJSDocParsing/link-ParseNone-file.ts.diff b/tests/baselines/reference/skipJSDocParsing/link-ParseNone-file.ts.diff index bcb71c32e13..8a04321c7a0 100644 --- a/tests/baselines/reference/skipJSDocParsing/link-ParseNone-file.ts.diff +++ b/tests/baselines/reference/skipJSDocParsing/link-ParseNone-file.ts.diff @@ -15,7 +15,7 @@ - "flags": "JSDoc", - "modifierFlagsCache": 0, - "transformFlags": 0, -- "comment": { +- "commentArray": { - "0": { - "kind": "JSDocText", - "pos": 32, diff --git a/tests/baselines/reference/skipJSDocParsing/see-ParseForTypeInfo-file.ts.diff b/tests/baselines/reference/skipJSDocParsing/see-ParseForTypeInfo-file.ts.diff index 3063fb1931b..a985b14b071 100644 --- a/tests/baselines/reference/skipJSDocParsing/see-ParseForTypeInfo-file.ts.diff +++ b/tests/baselines/reference/skipJSDocParsing/see-ParseForTypeInfo-file.ts.diff @@ -93,7 +93,7 @@ - "transformFlags": 0, - "escapedText": "see" - }, -- "comment": { +- "commentArray": { - "0": { - "kind": "JSDocText", - "pos": 42, @@ -142,7 +142,7 @@ - "transformFlags": 0, - "escapedText": "see" - }, -- "comment": { +- "commentArray": { - "0": { - "kind": "JSDocText", - "pos": 60, @@ -191,7 +191,7 @@ - "transformFlags": 0, - "escapedText": "see" - }, -- "comment": { +- "commentArray": { - "0": { - "kind": "JSDocText", - "pos": 82, diff --git a/tests/baselines/reference/skipJSDocParsing/see-ParseNone-file.js.diff b/tests/baselines/reference/skipJSDocParsing/see-ParseNone-file.js.diff index a341a7806e2..53f7941fd03 100644 --- a/tests/baselines/reference/skipJSDocParsing/see-ParseNone-file.js.diff +++ b/tests/baselines/reference/skipJSDocParsing/see-ParseNone-file.js.diff @@ -93,7 +93,7 @@ - "transformFlags": 0, - "escapedText": "see" - }, -- "comment": { +- "commentArray": { - "0": { - "kind": "JSDocText", - "pos": 42, @@ -142,7 +142,7 @@ - "transformFlags": 0, - "escapedText": "see" - }, -- "comment": { +- "commentArray": { - "0": { - "kind": "JSDocText", - "pos": 60, @@ -191,7 +191,7 @@ - "transformFlags": 0, - "escapedText": "see" - }, -- "comment": { +- "commentArray": { - "0": { - "kind": "JSDocText", - "pos": 82, diff --git a/tests/baselines/reference/skipJSDocParsing/see-ParseNone-file.ts.diff b/tests/baselines/reference/skipJSDocParsing/see-ParseNone-file.ts.diff index e8d9f5347f9..accc137cc52 100644 --- a/tests/baselines/reference/skipJSDocParsing/see-ParseNone-file.ts.diff +++ b/tests/baselines/reference/skipJSDocParsing/see-ParseNone-file.ts.diff @@ -93,7 +93,7 @@ - "transformFlags": 0, - "escapedText": "see" - }, -- "comment": { +- "commentArray": { - "0": { - "kind": "JSDocText", - "pos": 42, @@ -142,7 +142,7 @@ - "transformFlags": 0, - "escapedText": "see" - }, -- "comment": { +- "commentArray": { - "0": { - "kind": "JSDocText", - "pos": 60, @@ -191,7 +191,7 @@ - "transformFlags": 0, - "escapedText": "see" - }, -- "comment": { +- "commentArray": { - "0": { - "kind": "JSDocText", - "pos": 82,