From 648e4a912df7be2073264e8fd3ae41a9f599df73 Mon Sep 17 00:00:00 2001 From: Ron Buckton Date: Wed, 18 Sep 2024 14:01:41 -0400 Subject: [PATCH] migrate majority of parser to slim ast node --- src/compiler/_namespaces/ts.ts | 1 + src/compiler/ast.ts | 226 +- src/compiler/factory/astNodeFactory.ts | 3 +- src/compiler/factory/astNodeTests.ts | 507 +++-- src/compiler/forEachChild.ts | 1018 +++++++++ src/compiler/parser.ts | 2844 +++++++++--------------- src/compiler/utilities.ts | 33 +- src/compiler/utilitiesPublic.ts | 16 +- 8 files changed, 2533 insertions(+), 2115 deletions(-) create mode 100644 src/compiler/forEachChild.ts diff --git a/src/compiler/_namespaces/ts.ts b/src/compiler/_namespaces/ts.ts index ba2aa8541c6..22938bf674f 100644 --- a/src/compiler/_namespaces/ts.ts +++ b/src/compiler/_namespaces/ts.ts @@ -22,6 +22,7 @@ export * from "../factory/nodeTests.js"; export * from "../factory/nodeChildren.js"; export * from "../factory/utilities.js"; export * from "../factory/utilitiesPublic.js"; +export * from "../forEachChild.js"; export * from "../parser.js"; export * from "../commandLineParser.js"; export * from "../moduleNameResolver.js"; diff --git a/src/compiler/ast.ts b/src/compiler/ast.ts index dadf5c740ba..191e2e9d9db 100644 --- a/src/compiler/ast.ts +++ b/src/compiler/ast.ts @@ -90,21 +90,19 @@ export class AstNodeExtraFields { original: AstNode | undefined = undefined; emitNode: EmitNode | undefined = undefined; modifierFlagsCache: ts.ModifierFlags = ModifierFlags.None; - transformFlags: TransformFlags | undefined = undefined; - __pos: number | undefined = undefined; - __end: number | undefined = undefined; + transformFlags: TransformFlags = (-1 as TransformFlags); + __pos: number = -1; + __end: number = -1; } let astNodeCloneCore: (node: AstNode) => AstNode; let astNodeShadowCore: (node: AstNode) => AstNode; -let astNodeMaybeExtra: (node: AstNode) => AstNodeExtraFields | undefined; /** @internal */ export class AstNode = Node> { static { astNodeCloneCore = node => node.cloneCore(); astNodeShadowCore = node => node.shadowCore(); - astNodeMaybeExtra = node => node._extra; } private _node: N | undefined = undefined; @@ -115,11 +113,14 @@ export class AstNode = Node> | undefined = undefined; - flags: NodeFlags; + flags: NodeFlags = NodeFlags.None; pos = -1; end = -1; constructor(kind: N["kind"], data: N["data"], nodeConstructor: NodeConstructor, flags: ts.NodeFlags = NodeFlags.None) { + // catch any excess properties assigned to the Node + Object.preventExtensions(this); + this.kind = kind; this.data = data; this.flags = flags; @@ -149,23 +150,51 @@ export class AstNode = Node implements ts.Node { - readonly ast: AstNode>; + readonly ast: AstNode> = undefined!; constructor(ast: AstNode>) { - this.ast = ast; - // catch any excess properties assigned to the Node Object.preventExtensions(this); + + this.ast = ast; } get kind(): K { @@ -1028,16 +1057,16 @@ export class Node { private _extra: AstNodeArrayExtraFields | undefined = undefined; constructor(items: readonly N[], hasTrailingComma = false) { + // catch any excess properties assigned to the NodeArray + Object.preventExtensions(this); + this.items = items; this.hasTrailingComma = hasTrailingComma; } @@ -1273,7 +1305,9 @@ export class AstNodeArray { return this._extra?.hasTrailingComma ?? false; } set hasTrailingComma(value) { - this.extra.hasTrailingComma = value; + if (value !== this.hasTrailingComma) { + this.extra.hasTrailingComma = value; + } } get transformFlags(): ts.TransformFlags { @@ -1335,7 +1369,7 @@ export class NodeArray extends Array implements ts.NodeArray< get __pos(): number | undefined { // eslint-disable-line @typescript-eslint/naming-convention return astNodeArrayMaybeExtra(this.ast)?.__pos; - } + } set __pos(value) { // eslint-disable-line @typescript-eslint/naming-convention this.ast.extra.__pos = value; } @@ -1565,8 +1599,57 @@ export interface PrimaryExpression extends MemberExpression { export type AstPrimaryExpression = AstNode; /** @internal */ -export interface LiteralExpression extends PrimaryExpression { +export interface KeywordExpression extends PrimaryExpression, KeywordToken { + readonly ast: AstKeywordExpression; + readonly kind: TKind; +} + +/** @internal */ +export type AstKeywordExpression = AstNode>; + +/** @internal */ +export interface LiteralLikeNode extends Node { + readonly ast: AstLiteralLikeNode; + readonly data: AstLiteralLikeNodeData; + + text: string; + isUnterminated?: boolean | undefined; + hasExtendedUnicodeEscape?: boolean | undefined; +} + +/** @internal */ +export type AstLiteralLikeNode = AstNode; + +/** @internal */ +export interface AstLiteralLikeNodeData extends AstData { + text: string; + isUnterminated?: boolean | undefined; + hasExtendedUnicodeEscape?: boolean | undefined; +} + +/** @internal */ +export interface TemplateLiteralLikeNode extends LiteralLikeNode { + readonly ast: AstTemplateLiteralLikeNode; + readonly data: AstTemplateLiteralLikeNodeData; + rawText?: string | undefined; + /** @internal */ + templateFlags?: TokenFlags | undefined; +} + +/** @internal */ +export interface AstTemplateLiteralLikeNodeData extends AstLiteralLikeNodeData { + rawText?: string | undefined; + /** @internal */ + templateFlags?: TokenFlags | undefined; +} + +/** @internal */ +export type AstTemplateLiteralLikeNode = AstNode; + +/** @internal */ +export interface LiteralExpression extends PrimaryExpression, LiteralLikeNode { readonly ast: AstLiteralExpression; + readonly data: AstLiteralExpressionData; _literalExpressionBrand: any; get text(): string; @@ -1576,6 +1659,10 @@ export interface LiteralExpression extends PrimaryExpression { /** @internal */ export type AstLiteralExpression = AstNode; +/** @internal */ +export interface AstLiteralExpressionData extends AstLiteralLikeNodeData { +} + /** @internal */ export class Token extends Node implements ts.Token { public override getChildCount(_sourceFile?: ts.SourceFile): number { @@ -1668,7 +1755,7 @@ export class AstEndOfFileTokenData extends AstTokenData { } /** @internal */ -export class ThisExpression extends Token implements PrimaryExpression, FlowContainer, ts.ThisExpression { +export class ThisExpression extends Token implements KeywordExpression, FlowContainer, ts.ThisExpression { declare readonly ast: AstThisExpression; declare _primaryExpressionBrand: any; @@ -1693,7 +1780,7 @@ export class AstThisExpressionData extends AstTokenData { } /** @internal */ -export class SuperExpression extends Token implements PrimaryExpression, FlowContainer, ts.SuperExpression { +export class SuperExpression extends Token implements KeywordExpression, FlowContainer, ts.SuperExpression { declare readonly ast: AstSuperExpression; declare _primaryExpressionBrand: any; @@ -1718,7 +1805,7 @@ export class AstSuperExpressionData extends AstTokenData { } /** @internal */ -export class ImportExpression extends Token implements PrimaryExpression, ts.ImportExpression { +export class ImportExpression extends Token implements KeywordExpression, ts.ImportExpression { declare readonly ast: AstImportExpression; declare _primaryExpressionBrand: any; @@ -1730,7 +1817,7 @@ export class ImportExpression extends Token implements } /** @internal */ -export class NullLiteral extends Token implements PrimaryExpression, ts.NullLiteral { +export class NullLiteral extends Token implements KeywordExpression, ts.NullLiteral { declare readonly ast: AstNullLiteral; declare _primaryExpressionBrand: any; @@ -1742,7 +1829,7 @@ export class NullLiteral extends Token implements Primar } /** @internal */ -export class TrueLiteral extends Token implements PrimaryExpression, ts.TrueLiteral { +export class TrueLiteral extends Token implements KeywordExpression, ts.TrueLiteral { declare readonly ast: AstTrueLiteral; declare _primaryExpressionBrand: any; @@ -1754,7 +1841,7 @@ export class TrueLiteral extends Token implements Primar } /** @internal */ -export class FalseLiteral extends Token implements PrimaryExpression, ts.FalseLiteral { +export class FalseLiteral extends Token implements KeywordExpression, ts.FalseLiteral { declare readonly ast: AstFalseLiteral; declare _primaryExpressionBrand: any; @@ -4445,6 +4532,14 @@ export class ThisTypeNode extends Node export class AstThisTypeNodeData extends AstTypeScriptNodeData { } +/** @internal */ +export type FunctionOrConstructorTypeNode = + | FunctionTypeNode + | ConstructorTypeNode; + +/** @internal */ +export type AstFunctionOrConstructorTypeNode = AstNodeOneOf; + /** @internal */ export class FunctionTypeNode extends Node implements JSDocContainer, Declaration, LocalsContainer, ts.FunctionTypeNode { declare readonly ast: AstFunctionTypeNode; @@ -4518,11 +4613,11 @@ export class FunctionTypeNode extends Node | undefined = undefined; // initialized by parser (grammar error) typeParameters: AstNodeArray | undefined = undefined; parameters: AstNodeArray = undefined!; type: AstTypeNode = undefined!; typeArguments: AstNodeArray | undefined = undefined; // quick info - modifiers: AstNodeArray | undefined = undefined; // initialized by parser (grammar error) jsDoc: JSDocArray | undefined = undefined; // initialized by parser (JSDocContainer) symbol: Symbol = undefined!; // initialized by binder (Declaration) @@ -4883,6 +4978,14 @@ export class AstRestTypeNodeData extends AstTypeScriptNodeData { type: AstTypeNode = undefined!; } +/** @internal */ +export type UnionOrIntersectionTypeNode = + | UnionTypeNode + | IntersectionTypeNode; + +/** @internal */ +export type AstUnionOrIntersectionTypeNode = AstNodeOneOf; + /** @internal */ export class UnionTypeNode extends Node implements ts.UnionTypeNode { declare readonly ast: AstUnionTypeNode; @@ -7944,7 +8047,7 @@ export class AstJsxExpressionData extends AstData { } /** @internal */ -export class JsxText extends Token implements ts.JsxText { +export class JsxText extends Token implements ts.JsxText, LiteralLikeNode { declare readonly ast: AstJsxText; override get parent() { @@ -13533,6 +13636,69 @@ export type AstCommaListExpression = AstNode; /** @internal */ export type AstSyntheticReferenceExpression = AstNode; +// JSON + +/** @internal */ +export interface JsonMinusNumericLiteral extends PrefixUnaryExpression { + readonly ast: AstJsonMinusNumericLiteral; + readonly data: AstJsonMinusNumericLiteralData; + + readonly operator: SyntaxKind.MinusToken; + readonly operand: NumericLiteral; +} + +/** @internal */ +export interface AstJsonMinusNumericLiteralData extends AstPrefixUnaryExpressionData { + operator: SyntaxKind.MinusToken; + operand: AstNumericLiteral; +} + +/** @internal */ +export type AstJsonMinusNumericLiteral = AstNode; + +/** @internal */ +export type JsonObjectExpression = + | ObjectLiteralExpression + | ArrayLiteralExpression + | JsonMinusNumericLiteral + | NumericLiteral + | StringLiteral + | BooleanLiteral + | NullLiteral; + +/** @internal */ +export type AstJsonObjectExpression = AstNodeOneOf; + +/** @internal */ +export interface JsonObjectExpressionStatement extends ExpressionStatement { + readonly ast: AstJsonObjectExpressionStatement; + readonly data: AstJsonObjectExpressionStatementData; + readonly expression: JsonObjectExpression; +} + +/** @internal */ +export type AstJsonObjectExpressionStatement = AstNode; + +/** @internal */ +export interface AstJsonObjectExpressionStatementData extends AstExpressionStatementData { + expression: AstJsonObjectExpression; +} + +/** @internal */ +export interface JsonSourceFile extends SourceFile { + readonly ast: AstJsonSourceFile; + readonly data: AstJsonSourceFileData; + readonly statements: NodeArray; +} + +/** @internal */ +export type AstJsonSourceFile = AstNode; + +/** @internal */ +export interface AstJsonSourceFileData extends AstSourceFileData { + statements: AstNodeArray; +} + function propagateNameFlags(node: AstPropertyName | AstBindingPattern | AstNoSubstitutionTemplateLiteral | undefined) { return node?.kind === SyntaxKind.Identifier ? propagateIdentifierNameFlags(node) : propagateChildFlags(node); } diff --git a/src/compiler/factory/astNodeFactory.ts b/src/compiler/factory/astNodeFactory.ts index 664683ba494..659cea94723 100644 --- a/src/compiler/factory/astNodeFactory.ts +++ b/src/compiler/factory/astNodeFactory.ts @@ -347,6 +347,7 @@ import { SyntaxKind, TokenFlags, TokenSyntaxKind, + TransformFlags, Type, } from "../_namespaces/ts.js"; @@ -5482,7 +5483,7 @@ export function createAstNodeFactory(flags: NodeFactoryFlags, onFinishNode?: (no node.data.typeReferenceDirectives = typeReferences; node.data.hasNoDefaultLib = hasNoDefaultLib; node.data.libReferenceDirectives = libReferences; - node.extra.transformFlags = undefined; + node.extra.transformFlags = -1 as TransformFlags; return finish(node); } diff --git a/src/compiler/factory/astNodeTests.ts b/src/compiler/factory/astNodeTests.ts index 2de63a4b8a6..49154ccde35 100644 --- a/src/compiler/factory/astNodeTests.ts +++ b/src/compiler/factory/astNodeTests.ts @@ -10,13 +10,18 @@ import { AssertEntry, AssertsKeyword, AstCallChain, + AstDeclareKeyword, AstElementAccessChain, AsteriskToken, + AstHasJSDoc, + AstLeftHandSideExpression, AstNode, AstNonNullChain, + AstNumericLiteral, AstOptionalChainRoot, AstPropertyAccessChain, AstPropertyName, + AstStringLiteralLike, AsyncKeyword, AwaitExpression, AwaitKeyword, @@ -194,6 +199,7 @@ import { SemicolonClassElement, SetAccessorDeclaration, ShorthandPropertyAssignment, + skipAstOuterExpressions, SourceFile, SpreadAssignment, SpreadElement, @@ -236,759 +242,767 @@ import { YieldExpression, } from "../_namespaces/ts.ast.js"; import { + canHaveJSDoc, + isLeftHandSideExpressionKind, NodeFlags, + OuterExpressionKinds, SyntaxKind, } from "../_namespaces/ts.js"; // Literals /** @internal */ -export function isAstNumericLiteral(node: AstNode): node is AstNode { +export function isAstNumericLiteral(node: AstNode): node is AstNode { return node.kind === SyntaxKind.NumericLiteral; } /** @internal */ -export function isAstBigIntLiteral(node: AstNode): node is AstNode { +export function isAstBigIntLiteral(node: AstNode): node is AstNode { return node.kind === SyntaxKind.BigIntLiteral; } /** @internal */ -export function isAstStringLiteral(node: AstNode): node is AstNode { +export function isAstStringLiteral(node: AstNode): node is AstNode { return node.kind === SyntaxKind.StringLiteral; } /** @internal */ -export function isAstJsxText(node: AstNode): node is AstNode { +export function isAstJsxText(node: AstNode): node is AstNode { return node.kind === SyntaxKind.JsxText; } /** @internal */ -export function isAstRegularExpressionLiteral(node: AstNode): node is AstNode { +export function isAstRegularExpressionLiteral(node: AstNode): node is AstNode { return node.kind === SyntaxKind.RegularExpressionLiteral; } /** @internal */ -export function isAstNoSubstitutionTemplateLiteral(node: AstNode): node is AstNode { +export function isAstNoSubstitutionTemplateLiteral(node: AstNode): node is AstNode { return node.kind === SyntaxKind.NoSubstitutionTemplateLiteral; } // Pseudo-literals /** @internal */ -export function isAstTemplateHead(node: AstNode): node is AstNode { +export function isAstTemplateHead(node: AstNode): node is AstNode { return node.kind === SyntaxKind.TemplateHead; } /** @internal */ -export function isAstTemplateMiddle(node: AstNode): node is AstNode { +export function isAstTemplateMiddle(node: AstNode): node is AstNode { return node.kind === SyntaxKind.TemplateMiddle; } /** @internal */ -export function isAstTemplateTail(node: AstNode): node is AstNode { +export function isAstTemplateTail(node: AstNode): node is AstNode { return node.kind === SyntaxKind.TemplateTail; } // Punctuation /** @internal */ -export function isAstDotDotDotToken(node: AstNode): node is AstNode { +export function isAstDotDotDotToken(node: AstNode): node is AstNode { return node.kind === SyntaxKind.DotDotDotToken; } /** @internal */ -export function isAstCommaToken(node: AstNode): node is AstNode> { +export function isAstCommaToken(node: AstNode): node is AstNode> { return node.kind === SyntaxKind.CommaToken; } /** @internal */ -export function isAstPlusToken(node: AstNode): node is AstNode { +export function isAstPlusToken(node: AstNode): node is AstNode { return node.kind === SyntaxKind.PlusToken; } /** @internal */ -export function isAstMinusToken(node: AstNode): node is AstNode { +export function isAstMinusToken(node: AstNode): node is AstNode { return node.kind === SyntaxKind.MinusToken; } /** @internal */ -export function isAstAsteriskToken(node: AstNode): node is AstNode { +export function isAstAsteriskToken(node: AstNode): node is AstNode { return node.kind === SyntaxKind.AsteriskToken; } /** @internal */ -export function isAstExclamationToken(node: AstNode): node is AstNode { +export function isAstExclamationToken(node: AstNode): node is AstNode { return node.kind === SyntaxKind.ExclamationToken; } /** @internal */ -export function isAstQuestionToken(node: AstNode): node is AstNode { +export function isAstQuestionToken(node: AstNode): node is AstNode { return node.kind === SyntaxKind.QuestionToken; } /** @internal */ -export function isAstColonToken(node: AstNode): node is AstNode { +export function isAstColonToken(node: AstNode): node is AstNode { return node.kind === SyntaxKind.ColonToken; } /** @internal */ -export function isAstQuestionDotToken(node: AstNode): node is AstNode { +export function isAstQuestionDotToken(node: AstNode): node is AstNode { return node.kind === SyntaxKind.QuestionDotToken; } /** @internal */ -export function isAstEqualsGreaterThanToken(node: AstNode): node is AstNode { +export function isAstEqualsGreaterThanToken(node: AstNode): node is AstNode { return node.kind === SyntaxKind.EqualsGreaterThanToken; } // Identifiers /** @internal */ -export function isAstIdentifier(node: AstNode): node is AstNode { +export function isAstIdentifier(node: AstNode): node is AstNode { return node.kind === SyntaxKind.Identifier; } /** @internal */ -export function isAstPrivateIdentifier(node: AstNode): node is AstNode { +export function isAstPrivateIdentifier(node: AstNode): node is AstNode { return node.kind === SyntaxKind.PrivateIdentifier; } // Reserved Words /** @internal */ -export function isAstExportModifier(node: AstNode): node is AstNode { +export function isAstExportModifier(node: AstNode): node is AstNode { return node.kind === SyntaxKind.ExportKeyword; } /** @internal */ -export function isAstDefaultModifier(node: AstNode): node is AstNode { +export function isAstDefaultModifier(node: AstNode): node is AstNode { return node.kind === SyntaxKind.DefaultKeyword; } /** @internal */ -export function isAstAsyncModifier(node: AstNode): node is AstNode { +export function isAstAsyncModifier(node: AstNode): node is AstNode { return node.kind === SyntaxKind.AsyncKeyword; } /** @internal */ -export function isAstAssertsKeyword(node: AstNode): node is AstNode { +export function isAstAssertsKeyword(node: AstNode): node is AstNode { return node.kind === SyntaxKind.AssertsKeyword; } /** @internal */ -export function isAstAwaitKeyword(node: AstNode): node is AstNode { +export function isAstAwaitKeyword(node: AstNode): node is AstNode { return node.kind === SyntaxKind.AwaitKeyword; } /** @internal */ -export function isAstReadonlyKeyword(node: AstNode): node is AstNode { +export function isAstReadonlyKeyword(node: AstNode): node is AstNode { return node.kind === SyntaxKind.ReadonlyKeyword; } /** @internal */ -export function isAstStaticModifier(node: AstNode): node is AstNode { +export function isAstStaticModifier(node: AstNode): node is AstNode { return node.kind === SyntaxKind.StaticKeyword; } /** @internal */ -export function isAstAbstractModifier(node: AstNode): node is AstNode { +export function isAstAbstractModifier(node: AstNode): node is AstNode { return node.kind === SyntaxKind.AbstractKeyword; } /** @internal */ -export function isAstOverrideModifier(node: AstNode): node is AstNode { +export function isAstOverrideModifier(node: AstNode): node is AstNode { return node.kind === SyntaxKind.OverrideKeyword; } /** @internal */ -export function isAstAccessorModifier(node: AstNode): node is AstNode { +export function isAstAccessorModifier(node: AstNode): node is AstNode { return node.kind === SyntaxKind.AccessorKeyword; } /** @internal */ -export function isAstSuperKeyword(node: AstNode): node is AstNode { +export function isAstSuperKeyword(node: AstNode): node is AstNode { return node.kind === SyntaxKind.SuperKeyword; } /** @internal */ -export function isAstImportKeyword(node: AstNode): node is AstNode { +export function isAstImportKeyword(node: AstNode): node is AstNode { return node.kind === SyntaxKind.ImportKeyword; } /** @internal */ -export function isAstCaseKeyword(node: AstNode): node is AstNode { +export function isAstCaseKeyword(node: AstNode): node is AstNode { return node.kind === SyntaxKind.CaseKeyword; } +/** @internal */ +export function isAstDeclareKeyword(node: AstNode): node is AstDeclareKeyword { + return node.kind === SyntaxKind.DeclareKeyword; +} + // Names /** @internal */ -export function isAstQualifiedName(node: AstNode): node is AstNode { +export function isAstQualifiedName(node: AstNode): node is AstNode { return node.kind === SyntaxKind.QualifiedName; } /** @internal */ -export function isAstComputedPropertyName(node: AstNode): node is AstNode { +export function isAstComputedPropertyName(node: AstNode): node is AstNode { return node.kind === SyntaxKind.ComputedPropertyName; } // Signature elements /** @internal */ -export function isAstTypeParameterDeclaration(node: AstNode): node is AstNode { +export function isAstTypeParameterDeclaration(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 isAstParameter(node: AstNode): node is AstNode { return node.kind === SyntaxKind.Parameter; } /** @internal */ -export function isAstDecorator(node: AstNode): node is AstNode { +export function isAstDecorator(node: AstNode): node is AstNode { return node.kind === SyntaxKind.Decorator; } // TypeMember /** @internal */ -export function isAstPropertySignature(node: AstNode): node is AstNode { +export function isAstPropertySignature(node: AstNode): node is AstNode { return node.kind === SyntaxKind.PropertySignature; } /** @internal */ -export function isAstPropertyDeclaration(node: AstNode): node is AstNode { +export function isAstPropertyDeclaration(node: AstNode): node is AstNode { return node.kind === SyntaxKind.PropertyDeclaration; } /** @internal */ -export function isAstMethodSignature(node: AstNode): node is AstNode { +export function isAstMethodSignature(node: AstNode): node is AstNode { return node.kind === SyntaxKind.MethodSignature; } /** @internal */ -export function isAstMethodDeclaration(node: AstNode): node is AstNode { +export function isAstMethodDeclaration(node: AstNode): node is AstNode { return node.kind === SyntaxKind.MethodDeclaration; } /** @internal */ -export function isAstClassStaticBlockDeclaration(node: AstNode): node is AstNode { +export function isAstClassStaticBlockDeclaration(node: AstNode): node is AstNode { return node.kind === SyntaxKind.ClassStaticBlockDeclaration; } /** @internal */ -export function isAstConstructorDeclaration(node: AstNode): node is AstNode { +export function isAstConstructorDeclaration(node: AstNode): node is AstNode { return node.kind === SyntaxKind.Constructor; } /** @internal */ -export function isAstGetAccessorDeclaration(node: AstNode): node is AstNode { +export function isAstGetAccessorDeclaration(node: AstNode): node is AstNode { return node.kind === SyntaxKind.GetAccessor; } /** @internal */ -export function isAstSetAccessorDeclaration(node: AstNode): node is AstNode { +export function isAstSetAccessorDeclaration(node: AstNode): node is AstNode { return node.kind === SyntaxKind.SetAccessor; } /** @internal */ -export function isAstCallSignatureDeclaration(node: AstNode): node is AstNode { +export function isAstCallSignatureDeclaration(node: AstNode): node is AstNode { return node.kind === SyntaxKind.CallSignature; } /** @internal */ -export function isAstConstructSignatureDeclaration(node: AstNode): node is AstNode { +export function isAstConstructSignatureDeclaration(node: AstNode): node is AstNode { return node.kind === SyntaxKind.ConstructSignature; } /** @internal */ -export function isAstIndexSignatureDeclaration(node: AstNode): node is AstNode { +export function isAstIndexSignatureDeclaration(node: AstNode): node is AstNode { return node.kind === SyntaxKind.IndexSignature; } // Type /** @internal */ -export function isAstTypePredicateNode(node: AstNode): node is AstNode { +export function isAstTypePredicateNode(node: AstNode): node is AstNode { return node.kind === SyntaxKind.TypePredicate; } /** @internal */ -export function isAstTypeReferenceNode(node: AstNode): node is AstNode { +export function isAstTypeReferenceNode(node: AstNode): node is AstNode { return node.kind === SyntaxKind.TypeReference; } /** @internal */ -export function isAstFunctionTypeNode(node: AstNode): node is AstNode { +export function isAstFunctionTypeNode(node: AstNode): node is AstNode { return node.kind === SyntaxKind.FunctionType; } /** @internal */ -export function isAstConstructorTypeNode(node: AstNode): node is AstNode { +export function isAstConstructorTypeNode(node: AstNode): node is AstNode { return node.kind === SyntaxKind.ConstructorType; } /** @internal */ -export function isAstTypeQueryNode(node: AstNode): node is AstNode { +export function isAstTypeQueryNode(node: AstNode): node is AstNode { return node.kind === SyntaxKind.TypeQuery; } /** @internal */ -export function isAstTypeLiteralNode(node: AstNode): node is AstNode { +export function isAstTypeLiteralNode(node: AstNode): node is AstNode { return node.kind === SyntaxKind.TypeLiteral; } /** @internal */ -export function isAstArrayTypeNode(node: AstNode): node is AstNode { +export function isAstArrayTypeNode(node: AstNode): node is AstNode { return node.kind === SyntaxKind.ArrayType; } /** @internal */ -export function isAstTupleTypeNode(node: AstNode): node is AstNode { +export function isAstTupleTypeNode(node: AstNode): node is AstNode { return node.kind === SyntaxKind.TupleType; } /** @internal */ -export function isAstNamedTupleMember(node: AstNode): node is AstNode { +export function isAstNamedTupleMember(node: AstNode): node is AstNode { return node.kind === SyntaxKind.NamedTupleMember; } /** @internal */ -export function isAstOptionalTypeNode(node: AstNode): node is AstNode { +export function isAstOptionalTypeNode(node: AstNode): node is AstNode { return node.kind === SyntaxKind.OptionalType; } /** @internal */ -export function isAstRestTypeNode(node: AstNode): node is AstNode { +export function isAstRestTypeNode(node: AstNode): node is AstNode { return node.kind === SyntaxKind.RestType; } /** @internal */ -export function isAstUnionTypeNode(node: AstNode): node is AstNode { +export function isAstUnionTypeNode(node: AstNode): node is AstNode { return node.kind === SyntaxKind.UnionType; } /** @internal */ -export function isAstIntersectionTypeNode(node: AstNode): node is AstNode { +export function isAstIntersectionTypeNode(node: AstNode): node is AstNode { return node.kind === SyntaxKind.IntersectionType; } /** @internal */ -export function isAstConditionalTypeNode(node: AstNode): node is AstNode { +export function isAstConditionalTypeNode(node: AstNode): node is AstNode { return node.kind === SyntaxKind.ConditionalType; } /** @internal */ -export function isAstInferTypeNode(node: AstNode): node is AstNode { +export function isAstInferTypeNode(node: AstNode): node is AstNode { return node.kind === SyntaxKind.InferType; } /** @internal */ -export function isAstParenthesizedTypeNode(node: AstNode): node is AstNode { +export function isAstParenthesizedTypeNode(node: AstNode): node is AstNode { return node.kind === SyntaxKind.ParenthesizedType; } /** @internal */ -export function isAstThisTypeNode(node: AstNode): node is AstNode { +export function isAstThisTypeNode(node: AstNode): node is AstNode { return node.kind === SyntaxKind.ThisType; } /** @internal */ -export function isAstTypeOperatorNode(node: AstNode): node is AstNode { +export function isAstTypeOperatorNode(node: AstNode): node is AstNode { return node.kind === SyntaxKind.TypeOperator; } /** @internal */ -export function isAstIndexedAccessTypeNode(node: AstNode): node is AstNode { +export function isAstIndexedAccessTypeNode(node: AstNode): node is AstNode { return node.kind === SyntaxKind.IndexedAccessType; } /** @internal */ -export function isAstMappedTypeNode(node: AstNode): node is AstNode { +export function isAstMappedTypeNode(node: AstNode): node is AstNode { return node.kind === SyntaxKind.MappedType; } /** @internal */ -export function isAstLiteralTypeNode(node: AstNode): node is AstNode { +export function isAstLiteralTypeNode(node: AstNode): node is AstNode { return node.kind === SyntaxKind.LiteralType; } /** @internal */ -export function isAstImportTypeNode(node: AstNode): node is AstNode { +export function isAstImportTypeNode(node: AstNode): node is AstNode { return node.kind === SyntaxKind.ImportType; } /** @internal */ -export function isAstTemplateLiteralTypeSpan(node: AstNode): node is AstNode { +export function isAstTemplateLiteralTypeSpan(node: AstNode): node is AstNode { return node.kind === SyntaxKind.TemplateLiteralTypeSpan; } /** @internal */ -export function isAstTemplateLiteralTypeNode(node: AstNode): node is AstNode { +export function isAstTemplateLiteralTypeNode(node: AstNode): node is AstNode { return node.kind === SyntaxKind.TemplateLiteralType; } // Binding patterns /** @internal */ -export function isAstObjectBindingPattern(node: AstNode): node is AstNode { +export function isAstObjectBindingPattern(node: AstNode): node is AstNode { return node.kind === SyntaxKind.ObjectBindingPattern; } /** @internal */ -export function isAstArrayBindingPattern(node: AstNode): node is AstNode { +export function isAstArrayBindingPattern(node: AstNode): node is AstNode { return node.kind === SyntaxKind.ArrayBindingPattern; } /** @internal */ -export function isAstBindingElement(node: AstNode): node is AstNode { +export function isAstBindingElement(node: AstNode): node is AstNode { return node.kind === SyntaxKind.BindingElement; } // Expression /** @internal */ -export function isAstArrayLiteralExpression(node: AstNode): node is AstNode { +export function isAstArrayLiteralExpression(node: AstNode): node is AstNode { return node.kind === SyntaxKind.ArrayLiteralExpression; } /** @internal */ -export function isAstObjectLiteralExpression(node: AstNode): node is AstNode { +export function isAstObjectLiteralExpression(node: AstNode): node is AstNode { return node.kind === SyntaxKind.ObjectLiteralExpression; } /** @internal */ -export function isAstPropertyAccessExpression(node: AstNode): node is AstNode { +export function isAstPropertyAccessExpression(node: AstNode): node is AstNode { return node.kind === SyntaxKind.PropertyAccessExpression; } /** @internal */ -export function isAstElementAccessExpression(node: AstNode): node is AstNode { +export function isAstElementAccessExpression(node: AstNode): node is AstNode { return node.kind === SyntaxKind.ElementAccessExpression; } /** @internal */ -export function isAstCallExpression(node: AstNode): node is AstNode { +export function isAstCallExpression(node: AstNode): node is AstNode { return node.kind === SyntaxKind.CallExpression; } /** @internal */ -export function isAstNewExpression(node: AstNode): node is AstNode { +export function isAstNewExpression(node: AstNode): node is AstNode { return node.kind === SyntaxKind.NewExpression; } /** @internal */ -export function isAstTaggedTemplateExpression(node: AstNode): node is AstNode { +export function isAstTaggedTemplateExpression(node: AstNode): node is AstNode { return node.kind === SyntaxKind.TaggedTemplateExpression; } /** @internal */ -export function isAstTypeAssertionExpression(node: AstNode): node is AstNode { +export function isAstTypeAssertionExpression(node: AstNode): node is AstNode { return node.kind === SyntaxKind.TypeAssertionExpression; } /** @internal */ -export function isAstParenthesizedExpression(node: AstNode): node is AstNode { +export function isAstParenthesizedExpression(node: AstNode): node is AstNode { return node.kind === SyntaxKind.ParenthesizedExpression; } /** @internal */ -export function isAstFunctionExpression(node: AstNode): node is AstNode { +export function isAstFunctionExpression(node: AstNode): node is AstNode { return node.kind === SyntaxKind.FunctionExpression; } /** @internal */ -export function isAstArrowFunction(node: AstNode): node is AstNode { +export function isAstArrowFunction(node: AstNode): node is AstNode { return node.kind === SyntaxKind.ArrowFunction; } /** @internal */ -export function isAstDeleteExpression(node: AstNode): node is AstNode { +export function isAstDeleteExpression(node: AstNode): node is AstNode { return node.kind === SyntaxKind.DeleteExpression; } /** @internal */ -export function isAstTypeOfExpression(node: AstNode): node is AstNode { +export function isAstTypeOfExpression(node: AstNode): node is AstNode { return node.kind === SyntaxKind.TypeOfExpression; } /** @internal */ -export function isAstVoidExpression(node: AstNode): node is AstNode { +export function isAstVoidExpression(node: AstNode): node is AstNode { return node.kind === SyntaxKind.VoidExpression; } /** @internal */ -export function isAstAwaitExpression(node: AstNode): node is AstNode { +export function isAstAwaitExpression(node: AstNode): node is AstNode { return node.kind === SyntaxKind.AwaitExpression; } /** @internal */ -export function isAstPrefixUnaryExpression(node: AstNode): node is AstNode { +export function isAstPrefixUnaryExpression(node: AstNode): node is AstNode { return node.kind === SyntaxKind.PrefixUnaryExpression; } /** @internal */ -export function isAstPostfixUnaryExpression(node: AstNode): node is AstNode { +export function isAstPostfixUnaryExpression(node: AstNode): node is AstNode { return node.kind === SyntaxKind.PostfixUnaryExpression; } /** @internal */ -export function isAstBinaryExpression(node: AstNode): node is AstNode { +export function isAstBinaryExpression(node: AstNode): node is AstNode { return node.kind === SyntaxKind.BinaryExpression; } /** @internal */ -export function isAstConditionalExpression(node: AstNode): node is AstNode { +export function isAstConditionalExpression(node: AstNode): node is AstNode { return node.kind === SyntaxKind.ConditionalExpression; } /** @internal */ -export function isAstTemplateExpression(node: AstNode): node is AstNode { +export function isAstTemplateExpression(node: AstNode): node is AstNode { return node.kind === SyntaxKind.TemplateExpression; } /** @internal */ -export function isAstYieldExpression(node: AstNode): node is AstNode { +export function isAstYieldExpression(node: AstNode): node is AstNode { return node.kind === SyntaxKind.YieldExpression; } /** @internal */ -export function isAstSpreadElement(node: AstNode): node is AstNode { +export function isAstSpreadElement(node: AstNode): node is AstNode { return node.kind === SyntaxKind.SpreadElement; } /** @internal */ -export function isAstClassExpression(node: AstNode): node is AstNode { +export function isAstClassExpression(node: AstNode): node is AstNode { return node.kind === SyntaxKind.ClassExpression; } /** @internal */ -export function isAstOmittedExpression(node: AstNode): node is AstNode { +export function isAstOmittedExpression(node: AstNode): node is AstNode { return node.kind === SyntaxKind.OmittedExpression; } /** @internal */ -export function isAstExpressionWithTypeArguments(node: AstNode): node is AstNode { +export function isAstExpressionWithTypeArguments(node: AstNode): node is AstNode { return node.kind === SyntaxKind.ExpressionWithTypeArguments; } /** @internal */ -export function isAstAsExpression(node: AstNode): node is AstNode { +export function isAstAsExpression(node: AstNode): node is AstNode { return node.kind === SyntaxKind.AsExpression; } /** @internal */ -export function isAstSatisfiesExpression(node: AstNode): node is AstNode { +export function isAstSatisfiesExpression(node: AstNode): node is AstNode { return node.kind === SyntaxKind.SatisfiesExpression; } /** @internal */ -export function isAstNonNullExpression(node: AstNode): node is AstNode { +export function isAstNonNullExpression(node: AstNode): node is AstNode { return node.kind === SyntaxKind.NonNullExpression; } /** @internal */ -export function isAstMetaProperty(node: AstNode): node is AstNode { +export function isAstMetaProperty(node: AstNode): node is AstNode { return node.kind === SyntaxKind.MetaProperty; } /** @internal */ -export function isAstSyntheticExpression(node: AstNode): node is AstNode { +export function isAstSyntheticExpression(node: AstNode): node is AstNode { return node.kind === SyntaxKind.SyntheticExpression; } /** @internal */ -export function isAstPartiallyEmittedExpression(node: AstNode): node is AstNode { +export function isAstPartiallyEmittedExpression(node: AstNode): node is AstNode { return node.kind === SyntaxKind.PartiallyEmittedExpression; } /** @internal */ -export function isAstCommaListExpression(node: AstNode): node is AstNode { +export function isAstCommaListExpression(node: AstNode): node is AstNode { return node.kind === SyntaxKind.CommaListExpression; } // Misc /** @internal */ -export function isAstTemplateSpan(node: AstNode): node is AstNode { +export function isAstTemplateSpan(node: AstNode): node is AstNode { return node.kind === SyntaxKind.TemplateSpan; } /** @internal */ -export function isAstSemicolonClassElement(node: AstNode): node is AstNode { +export function isAstSemicolonClassElement(node: AstNode): node is AstNode { return node.kind === SyntaxKind.SemicolonClassElement; } // Elements /** @internal */ -export function isAstBlock(node: AstNode): node is AstNode { +export function isAstBlock(node: AstNode): node is AstNode { return node.kind === SyntaxKind.Block; } /** @internal */ -export function isAstVariableStatement(node: AstNode): node is AstNode { +export function isAstVariableStatement(node: AstNode): node is AstNode { return node.kind === SyntaxKind.VariableStatement; } /** @internal */ -export function isAstEmptyStatement(node: AstNode): node is AstNode { +export function isAstEmptyStatement(node: AstNode): node is AstNode { return node.kind === SyntaxKind.EmptyStatement; } /** @internal */ -export function isAstExpressionStatement(node: AstNode): node is AstNode { +export function isAstExpressionStatement(node: AstNode): node is AstNode { return node.kind === SyntaxKind.ExpressionStatement; } /** @internal */ -export function isAstIfStatement(node: AstNode): node is AstNode { +export function isAstIfStatement(node: AstNode): node is AstNode { return node.kind === SyntaxKind.IfStatement; } /** @internal */ -export function isAstDoStatement(node: AstNode): node is AstNode { +export function isAstDoStatement(node: AstNode): node is AstNode { return node.kind === SyntaxKind.DoStatement; } /** @internal */ -export function isAstWhileStatement(node: AstNode): node is AstNode { +export function isAstWhileStatement(node: AstNode): node is AstNode { return node.kind === SyntaxKind.WhileStatement; } /** @internal */ -export function isAstForStatement(node: AstNode): node is AstNode { +export function isAstForStatement(node: AstNode): node is AstNode { return node.kind === SyntaxKind.ForStatement; } /** @internal */ -export function isAstForInStatement(node: AstNode): node is AstNode { +export function isAstForInStatement(node: AstNode): node is AstNode { return node.kind === SyntaxKind.ForInStatement; } /** @internal */ -export function isAstForOfStatement(node: AstNode): node is AstNode { +export function isAstForOfStatement(node: AstNode): node is AstNode { return node.kind === SyntaxKind.ForOfStatement; } /** @internal */ -export function isAstContinueStatement(node: AstNode): node is AstNode { +export function isAstContinueStatement(node: AstNode): node is AstNode { return node.kind === SyntaxKind.ContinueStatement; } /** @internal */ -export function isAstBreakStatement(node: AstNode): node is AstNode { +export function isAstBreakStatement(node: AstNode): node is AstNode { return node.kind === SyntaxKind.BreakStatement; } /** @internal */ -export function isAstReturnStatement(node: AstNode): node is AstNode { +export function isAstReturnStatement(node: AstNode): node is AstNode { return node.kind === SyntaxKind.ReturnStatement; } /** @internal */ -export function isAstWithStatement(node: AstNode): node is AstNode { +export function isAstWithStatement(node: AstNode): node is AstNode { return node.kind === SyntaxKind.WithStatement; } /** @internal */ -export function isAstSwitchStatement(node: AstNode): node is AstNode { +export function isAstSwitchStatement(node: AstNode): node is AstNode { return node.kind === SyntaxKind.SwitchStatement; } /** @internal */ -export function isAstLabeledStatement(node: AstNode): node is AstNode { +export function isAstLabeledStatement(node: AstNode): node is AstNode { return node.kind === SyntaxKind.LabeledStatement; } /** @internal */ -export function isAstThrowStatement(node: AstNode): node is AstNode { +export function isAstThrowStatement(node: AstNode): node is AstNode { return node.kind === SyntaxKind.ThrowStatement; } /** @internal */ -export function isAstTryStatement(node: AstNode): node is AstNode { +export function isAstTryStatement(node: AstNode): node is AstNode { return node.kind === SyntaxKind.TryStatement; } /** @internal */ -export function isAstDebuggerStatement(node: AstNode): node is AstNode { +export function isAstDebuggerStatement(node: AstNode): node is AstNode { return node.kind === SyntaxKind.DebuggerStatement; } /** @internal */ -export function isAstVariableDeclaration(node: AstNode): node is AstNode { +export function isAstVariableDeclaration(node: AstNode): node is AstNode { return node.kind === SyntaxKind.VariableDeclaration; } /** @internal */ -export function isAstVariableDeclarationList(node: AstNode): node is AstNode { +export function isAstVariableDeclarationList(node: AstNode): node is AstNode { return node.kind === SyntaxKind.VariableDeclarationList; } /** @internal */ -export function isAstFunctionDeclaration(node: AstNode): node is AstNode { +export function isAstFunctionDeclaration(node: AstNode): node is AstNode { return node.kind === SyntaxKind.FunctionDeclaration; } /** @internal */ -export function isAstClassDeclaration(node: AstNode): node is AstNode { +export function isAstClassDeclaration(node: AstNode): node is AstNode { return node.kind === SyntaxKind.ClassDeclaration; } /** @internal */ -export function isAstInterfaceDeclaration(node: AstNode): node is AstNode { +export function isAstInterfaceDeclaration(node: AstNode): node is AstNode { return node.kind === SyntaxKind.InterfaceDeclaration; } /** @internal */ -export function isAstTypeAliasDeclaration(node: AstNode): node is AstNode { +export function isAstTypeAliasDeclaration(node: AstNode): node is AstNode { return node.kind === SyntaxKind.TypeAliasDeclaration; } /** @internal */ -export function isAstEnumDeclaration(node: AstNode): node is AstNode { +export function isAstEnumDeclaration(node: AstNode): node is AstNode { return node.kind === SyntaxKind.EnumDeclaration; } /** @internal */ -export function isAstModuleDeclaration(node: AstNode): node is AstNode { +export function isAstModuleDeclaration(node: AstNode): node is AstNode { return node.kind === SyntaxKind.ModuleDeclaration; } /** @internal */ -export function isAstModuleBlock(node: AstNode): node is AstNode { +export function isAstModuleBlock(node: AstNode): node is AstNode { return node.kind === SyntaxKind.ModuleBlock; } /** @internal */ -export function isAstCaseBlock(node: AstNode): node is AstNode { +export function isAstCaseBlock(node: AstNode): node is AstNode { return node.kind === SyntaxKind.CaseBlock; } /** @internal */ -export function isAstNamespaceExportDeclaration(node: AstNode): node is AstNode { +export function isAstNamespaceExportDeclaration(node: AstNode): node is AstNode { return node.kind === SyntaxKind.NamespaceExportDeclaration; } /** @internal */ -export function isAstImportEqualsDeclaration(node: AstNode): node is AstNode { +export function isAstImportEqualsDeclaration(node: AstNode): node is AstNode { return node.kind === SyntaxKind.ImportEqualsDeclaration; } /** @internal */ -export function isAstImportDeclaration(node: AstNode): node is AstNode { +export function isAstImportDeclaration(node: AstNode): node is AstNode { return node.kind === SyntaxKind.ImportDeclaration; } /** @internal */ -export function isAstImportClause(node: AstNode): node is AstNode { +export function isAstImportClause(node: AstNode): node is AstNode { return node.kind === SyntaxKind.ImportClause; } /** @internal */ -export function isAstImportTypeAssertionContainer(node: AstNode): node is AstNode { +export function isAstImportTypeAssertionContainer(node: AstNode): node is AstNode { return node.kind === SyntaxKind.ImportTypeAssertionContainer; } @@ -996,7 +1010,7 @@ export function isAstImportTypeAssertionContainer(node: AstNode): node is * @deprecated * @internal */ -export function isAstAssertClause(node: AstNode): node is AstNode { +export function isAstAssertClause(node: AstNode): node is AstNode { return node.kind === SyntaxKind.AssertClause; } @@ -1004,203 +1018,203 @@ export function isAstAssertClause(node: AstNode): node is AstNode): node is AstNode { +export function isAstAssertEntry(node: AstNode): node is AstNode { return node.kind === SyntaxKind.AssertEntry; } /** @internal */ -export function isAstImportAttributes(node: AstNode): node is AstNode { +export function isAstImportAttributes(node: AstNode): node is AstNode { return node.kind === SyntaxKind.ImportAttributes; } /** @internal */ -export function isAstImportAttribute(node: AstNode): node is AstNode { +export function isAstImportAttribute(node: AstNode): node is AstNode { return node.kind === SyntaxKind.ImportAttribute; } /** @internal */ -export function isAstNamespaceImport(node: AstNode): node is AstNode { +export function isAstNamespaceImport(node: AstNode): node is AstNode { return node.kind === SyntaxKind.NamespaceImport; } /** @internal */ -export function isAstNamespaceExport(node: AstNode): node is AstNode { +export function isAstNamespaceExport(node: AstNode): node is AstNode { return node.kind === SyntaxKind.NamespaceExport; } /** @internal */ -export function isAstNamedImports(node: AstNode): node is AstNode { +export function isAstNamedImports(node: AstNode): node is AstNode { return node.kind === SyntaxKind.NamedImports; } /** @internal */ -export function isAstImportSpecifier(node: AstNode): node is AstNode { +export function isAstImportSpecifier(node: AstNode): node is AstNode { return node.kind === SyntaxKind.ImportSpecifier; } /** @internal */ -export function isAstExportAssignment(node: AstNode): node is AstNode { +export function isAstExportAssignment(node: AstNode): node is AstNode { return node.kind === SyntaxKind.ExportAssignment; } /** @internal */ -export function isAstExportDeclaration(node: AstNode): node is AstNode { +export function isAstExportDeclaration(node: AstNode): node is AstNode { return node.kind === SyntaxKind.ExportDeclaration; } /** @internal */ -export function isAstNamedExports(node: AstNode): node is AstNode { +export function isAstNamedExports(node: AstNode): node is AstNode { return node.kind === SyntaxKind.NamedExports; } /** @internal */ -export function isAstExportSpecifier(node: AstNode): node is AstNode { +export function isAstExportSpecifier(node: AstNode): node is AstNode { return node.kind === SyntaxKind.ExportSpecifier; } /** @internal */ -export function isAstModuleExportName(node: AstNode): node is AstNode { +export function isAstModuleExportName(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 isAstMissingDeclaration(node: AstNode): node is AstNode { return node.kind === SyntaxKind.MissingDeclaration; } /** @internal */ -export function isAstNotEmittedStatement(node: AstNode): node is AstNode { +export function isAstNotEmittedStatement(node: AstNode): node is AstNode { return node.kind === SyntaxKind.NotEmittedStatement; } /** @internal */ -export function isAstSyntheticReference(node: AstNode): node is AstNode { +export function isAstSyntheticReference(node: AstNode): node is AstNode { return node.kind === SyntaxKind.SyntheticReferenceExpression; } // Module References /** @internal */ -export function isAstExternalModuleReference(node: AstNode): node is AstNode { +export function isAstExternalModuleReference(node: AstNode): node is AstNode { return node.kind === SyntaxKind.ExternalModuleReference; } // JSX /** @internal */ -export function isAstJsxElement(node: AstNode): node is AstNode { +export function isAstJsxElement(node: AstNode): node is AstNode { return node.kind === SyntaxKind.JsxElement; } /** @internal */ -export function isAstJsxSelfClosingElement(node: AstNode): node is AstNode { +export function isAstJsxSelfClosingElement(node: AstNode): node is AstNode { return node.kind === SyntaxKind.JsxSelfClosingElement; } /** @internal */ -export function isAstJsxOpeningElement(node: AstNode): node is AstNode { +export function isAstJsxOpeningElement(node: AstNode): node is AstNode { return node.kind === SyntaxKind.JsxOpeningElement; } /** @internal */ -export function isAstJsxClosingElement(node: AstNode): node is AstNode { +export function isAstJsxClosingElement(node: AstNode): node is AstNode { return node.kind === SyntaxKind.JsxClosingElement; } /** @internal */ -export function isAstJsxFragment(node: AstNode): node is AstNode { +export function isAstJsxFragment(node: AstNode): node is AstNode { return node.kind === SyntaxKind.JsxFragment; } /** @internal */ -export function isAstJsxOpeningFragment(node: AstNode): node is AstNode { +export function isAstJsxOpeningFragment(node: AstNode): node is AstNode { return node.kind === SyntaxKind.JsxOpeningFragment; } /** @internal */ -export function isAstJsxClosingFragment(node: AstNode): node is AstNode { +export function isAstJsxClosingFragment(node: AstNode): node is AstNode { return node.kind === SyntaxKind.JsxClosingFragment; } /** @internal */ -export function isAstJsxAttribute(node: AstNode): node is AstNode { +export function isAstJsxAttribute(node: AstNode): node is AstNode { return node.kind === SyntaxKind.JsxAttribute; } /** @internal */ -export function isAstJsxAttributes(node: AstNode): node is AstNode { +export function isAstJsxAttributes(node: AstNode): node is AstNode { return node.kind === SyntaxKind.JsxAttributes; } /** @internal */ -export function isAstJsxSpreadAttribute(node: AstNode): node is AstNode { +export function isAstJsxSpreadAttribute(node: AstNode): node is AstNode { return node.kind === SyntaxKind.JsxSpreadAttribute; } /** @internal */ -export function isAstJsxExpression(node: AstNode): node is AstNode { +export function isAstJsxExpression(node: AstNode): node is AstNode { return node.kind === SyntaxKind.JsxExpression; } /** @internal */ -export function isAstJsxNamespacedName(node: AstNode): node is AstNode { +export function isAstJsxNamespacedName(node: AstNode): node is AstNode { return node.kind === SyntaxKind.JsxNamespacedName; } // Clauses /** @internal */ -export function isAstCaseClause(node: AstNode): node is AstNode { +export function isAstCaseClause(node: AstNode): node is AstNode { return node.kind === SyntaxKind.CaseClause; } /** @internal */ -export function isAstDefaultClause(node: AstNode): node is AstNode { +export function isAstDefaultClause(node: AstNode): node is AstNode { return node.kind === SyntaxKind.DefaultClause; } /** @internal */ -export function isAstHeritageClause(node: AstNode): node is AstNode { +export function isAstHeritageClause(node: AstNode): node is AstNode { return node.kind === SyntaxKind.HeritageClause; } /** @internal */ -export function isAstCatchClause(node: AstNode): node is AstNode { +export function isAstCatchClause(node: AstNode): node is AstNode { return node.kind === SyntaxKind.CatchClause; } // Property assignments /** @internal */ -export function isAstPropertyAssignment(node: AstNode): node is AstNode { +export function isAstPropertyAssignment(node: AstNode): node is AstNode { return node.kind === SyntaxKind.PropertyAssignment; } /** @internal */ -export function isAstShorthandPropertyAssignment(node: AstNode): node is AstNode { +export function isAstShorthandPropertyAssignment(node: AstNode): node is AstNode { return node.kind === SyntaxKind.ShorthandPropertyAssignment; } /** @internal */ -export function isAstSpreadAssignment(node: AstNode): node is AstNode { +export function isAstSpreadAssignment(node: AstNode): node is AstNode { return node.kind === SyntaxKind.SpreadAssignment; } // Enum /** @internal */ -export function isAstEnumMember(node: AstNode): node is AstNode { +export function isAstEnumMember(node: AstNode): node is AstNode { return node.kind === SyntaxKind.EnumMember; } /** @internal */ // Top-level nodes -export function isAstSourceFile(node: AstNode): node is AstNode { +export function isAstSourceFile(node: AstNode): node is AstNode { return node.kind === SyntaxKind.SourceFile; } /** @internal */ -export function isAstBundle(node: AstNode): node is AstNode { +export function isAstBundle(node: AstNode): node is AstNode { return node.kind === SyntaxKind.Bundle; } @@ -1209,214 +1223,214 @@ export function isAstBundle(node: AstNode): node is AstNode { // JSDoc Elements /** @internal */ -export function isAstJSDocTypeExpression(node: AstNode): node is AstNode { +export function isAstJSDocTypeExpression(node: AstNode): node is AstNode { return node.kind === SyntaxKind.JSDocTypeExpression; } /** @internal */ -export function isAstJSDocNameReference(node: AstNode): node is AstNode { +export function isAstJSDocNameReference(node: AstNode): node is AstNode { return node.kind === SyntaxKind.JSDocNameReference; } /** @internal */ -export function isAstJSDocMemberName(node: AstNode): node is AstNode { +export function isAstJSDocMemberName(node: AstNode): node is AstNode { return node.kind === SyntaxKind.JSDocMemberName; } /** @internal */ -export function isAstJSDocLink(node: AstNode): node is AstNode { +export function isAstJSDocLink(node: AstNode): node is AstNode { return node.kind === SyntaxKind.JSDocLink; } /** @internal */ -export function isAstJSDocLinkCode(node: AstNode): node is AstNode { +export function isAstJSDocLinkCode(node: AstNode): node is AstNode { return node.kind === SyntaxKind.JSDocLinkCode; } /** @internal */ -export function isAstJSDocLinkPlain(node: AstNode): node is AstNode { +export function isAstJSDocLinkPlain(node: AstNode): node is AstNode { return node.kind === SyntaxKind.JSDocLinkPlain; } /** @internal */ -export function isAstJSDocAllType(node: AstNode): node is AstNode { +export function isAstJSDocAllType(node: AstNode): node is AstNode { return node.kind === SyntaxKind.JSDocAllType; } /** @internal */ -export function isAstJSDocUnknownType(node: AstNode): node is AstNode { +export function isAstJSDocUnknownType(node: AstNode): node is AstNode { return node.kind === SyntaxKind.JSDocUnknownType; } /** @internal */ -export function isAstJSDocNullableType(node: AstNode): node is AstNode { +export function isAstJSDocNullableType(node: AstNode): node is AstNode { return node.kind === SyntaxKind.JSDocNullableType; } /** @internal */ -export function isAstJSDocNonNullableType(node: AstNode): node is AstNode { +export function isAstJSDocNonNullableType(node: AstNode): node is AstNode { return node.kind === SyntaxKind.JSDocNonNullableType; } /** @internal */ -export function isAstJSDocOptionalType(node: AstNode): node is AstNode { +export function isAstJSDocOptionalType(node: AstNode): node is AstNode { return node.kind === SyntaxKind.JSDocOptionalType; } /** @internal */ -export function isAstJSDocFunctionType(node: AstNode): node is AstNode { +export function isAstJSDocFunctionType(node: AstNode): node is AstNode { return node.kind === SyntaxKind.JSDocFunctionType; } /** @internal */ -export function isAstJSDocVariadicType(node: AstNode): node is AstNode { +export function isAstJSDocVariadicType(node: AstNode): node is AstNode { return node.kind === SyntaxKind.JSDocVariadicType; } /** @internal */ -export function isAstJSDocNamepathType(node: AstNode): node is AstNode { +export function isAstJSDocNamepathType(node: AstNode): node is AstNode { return node.kind === SyntaxKind.JSDocNamepathType; } /** @internal */ -export function isAstJSDoc(node: AstNode): node is AstNode { +export function isAstJSDoc(node: AstNode): node is AstNode { return node.kind === SyntaxKind.JSDoc; } /** @internal */ -export function isAstJSDocTypeLiteral(node: AstNode): node is AstNode { +export function isAstJSDocTypeLiteral(node: AstNode): node is AstNode { return node.kind === SyntaxKind.JSDocTypeLiteral; } /** @internal */ -export function isAstJSDocSignature(node: AstNode): node is AstNode { +export function isAstJSDocSignature(node: AstNode): node is AstNode { return node.kind === SyntaxKind.JSDocSignature; } // JSDoc Tags /** @internal */ -export function isAstJSDocAugmentsTag(node: AstNode): node is AstNode { +export function isAstJSDocAugmentsTag(node: AstNode): node is AstNode { return node.kind === SyntaxKind.JSDocAugmentsTag; } /** @internal */ -export function isAstJSDocAuthorTag(node: AstNode): node is AstNode { +export function isAstJSDocAuthorTag(node: AstNode): node is AstNode { return node.kind === SyntaxKind.JSDocAuthorTag; } /** @internal */ -export function isAstJSDocClassTag(node: AstNode): node is AstNode { +export function isAstJSDocClassTag(node: AstNode): node is AstNode { return node.kind === SyntaxKind.JSDocClassTag; } /** @internal */ -export function isAstJSDocCallbackTag(node: AstNode): node is AstNode { +export function isAstJSDocCallbackTag(node: AstNode): node is AstNode { return node.kind === SyntaxKind.JSDocCallbackTag; } /** @internal */ -export function isAstJSDocPublicTag(node: AstNode): node is AstNode { +export function isAstJSDocPublicTag(node: AstNode): node is AstNode { return node.kind === SyntaxKind.JSDocPublicTag; } /** @internal */ -export function isAstJSDocPrivateTag(node: AstNode): node is AstNode { +export function isAstJSDocPrivateTag(node: AstNode): node is AstNode { return node.kind === SyntaxKind.JSDocPrivateTag; } /** @internal */ -export function isAstJSDocProtectedTag(node: AstNode): node is AstNode { +export function isAstJSDocProtectedTag(node: AstNode): node is AstNode { return node.kind === SyntaxKind.JSDocProtectedTag; } /** @internal */ -export function isAstJSDocReadonlyTag(node: AstNode): node is AstNode { +export function isAstJSDocReadonlyTag(node: AstNode): node is AstNode { return node.kind === SyntaxKind.JSDocReadonlyTag; } /** @internal */ -export function isAstJSDocOverrideTag(node: AstNode): node is AstNode { +export function isAstJSDocOverrideTag(node: AstNode): node is AstNode { return node.kind === SyntaxKind.JSDocOverrideTag; } /** @internal */ -export function isAstJSDocOverloadTag(node: AstNode): node is AstNode { +export function isAstJSDocOverloadTag(node: AstNode): node is AstNode { return node.kind === SyntaxKind.JSDocOverloadTag; } /** @internal */ -export function isAstJSDocDeprecatedTag(node: AstNode): node is AstNode { +export function isAstJSDocDeprecatedTag(node: AstNode): node is AstNode { return node.kind === SyntaxKind.JSDocDeprecatedTag; } /** @internal */ -export function isAstJSDocSeeTag(node: AstNode): node is AstNode { +export function isAstJSDocSeeTag(node: AstNode): node is AstNode { return node.kind === SyntaxKind.JSDocSeeTag; } /** @internal */ -export function isAstJSDocEnumTag(node: AstNode): node is AstNode { +export function isAstJSDocEnumTag(node: AstNode): node is AstNode { return node.kind === SyntaxKind.JSDocEnumTag; } /** @internal */ -export function isAstJSDocParameterTag(node: AstNode): node is AstNode { +export function isAstJSDocParameterTag(node: AstNode): node is AstNode { return node.kind === SyntaxKind.JSDocParameterTag; } /** @internal */ -export function isAstJSDocReturnTag(node: AstNode): node is AstNode { +export function isAstJSDocReturnTag(node: AstNode): node is AstNode { return node.kind === SyntaxKind.JSDocReturnTag; } /** @internal */ -export function isAstJSDocThisTag(node: AstNode): node is AstNode { +export function isAstJSDocThisTag(node: AstNode): node is AstNode { return node.kind === SyntaxKind.JSDocThisTag; } /** @internal */ -export function isAstJSDocTypeTag(node: AstNode): node is AstNode { +export function isAstJSDocTypeTag(node: AstNode): node is AstNode { return node.kind === SyntaxKind.JSDocTypeTag; } /** @internal */ -export function isAstJSDocTemplateTag(node: AstNode): node is AstNode { +export function isAstJSDocTemplateTag(node: AstNode): node is AstNode { return node.kind === SyntaxKind.JSDocTemplateTag; } /** @internal */ -export function isAstJSDocTypedefTag(node: AstNode): node is AstNode { +export function isAstJSDocTypedefTag(node: AstNode): node is AstNode { return node.kind === SyntaxKind.JSDocTypedefTag; } /** @internal */ -export function isAstJSDocUnknownTag(node: AstNode): node is AstNode { +export function isAstJSDocUnknownTag(node: AstNode): node is AstNode { return node.kind === SyntaxKind.JSDocTag; } /** @internal */ -export function isAstJSDocPropertyTag(node: AstNode): node is AstNode { +export function isAstJSDocPropertyTag(node: AstNode): node is AstNode { return node.kind === SyntaxKind.JSDocPropertyTag; } /** @internal */ -export function isAstJSDocImplementsTag(node: AstNode): node is AstNode { +export function isAstJSDocImplementsTag(node: AstNode): node is AstNode { return node.kind === SyntaxKind.JSDocImplementsTag; } /** @internal */ -export function isAstJSDocSatisfiesTag(node: AstNode): node is AstNode { +export function isAstJSDocSatisfiesTag(node: AstNode): node is AstNode { return node.kind === SyntaxKind.JSDocSatisfiesTag; } /** @internal */ -export function isAstJSDocThrowsTag(node: AstNode): node is AstNode { +export function isAstJSDocThrowsTag(node: AstNode): node is AstNode { return node.kind === SyntaxKind.JSDocThrowsTag; } /** @internal */ -export function isAstJSDocImportTag(node: AstNode): node is AstNode { +export function isAstJSDocImportTag(node: AstNode): node is AstNode { return node.kind === SyntaxKind.JSDocImportTag; } @@ -1430,7 +1444,7 @@ export function isAstSyntaxList(n: Node): n is SyntaxList { // Unions /** @internal */ -export function isAstPropertyName(node: AstNode): node is AstPropertyName { +export function isAstPropertyName(node: AstNode): node is AstPropertyName { const kind = node.kind; return kind === SyntaxKind.Identifier || kind === SyntaxKind.PrivateIdentifier @@ -1440,27 +1454,27 @@ export function isAstPropertyName(node: AstNode): node is AstPropertyName } /** @internal */ -export function isAstPropertyAccessChain(node: AstNode): node is AstPropertyAccessChain { +export function isAstPropertyAccessChain(node: AstNode): node is AstPropertyAccessChain { return isAstPropertyAccessExpression(node) && !!(node.flags & NodeFlags.OptionalChain); } /** @internal */ -export function isAstElementAccessChain(node: AstNode): node is AstElementAccessChain { +export function isAstElementAccessChain(node: AstNode): node is AstElementAccessChain { return isAstElementAccessExpression(node) && !!(node.flags & NodeFlags.OptionalChain); } /** @internal */ -export function isAstCallChain(node: AstNode): node is AstCallChain { +export function isAstCallChain(node: AstNode): node is AstCallChain { return isAstCallExpression(node) && !!(node.flags & NodeFlags.OptionalChain); } /** @internal */ -export function isAstNonNullChain(node: AstNode): node is AstNonNullChain { +export function isAstNonNullChain(node: AstNode): node is AstNonNullChain { return isAstNonNullExpression(node) && !!(node.flags & NodeFlags.OptionalChain); } /** @internal */ -export function isAstOptionalChain(node: AstNode): node is AstPropertyAccessChain | AstElementAccessChain | AstCallChain | AstNonNullChain { +export function isAstOptionalChain(node: AstNode): node is AstPropertyAccessChain | AstElementAccessChain | AstCallChain | AstNonNullChain { const kind = node.kind; return !!(node.flags & NodeFlags.OptionalChain) && (kind === SyntaxKind.PropertyAccessExpression @@ -1470,6 +1484,33 @@ export function isAstOptionalChain(node: AstNode): node is AstPropertyAcce } /** @internal */ -export function isAstOptionalChainRoot(node: AstNode): node is AstOptionalChainRoot { +export function isAstOptionalChainRoot(node: AstNode): node is AstOptionalChainRoot { return isAstOptionalChain(node) && !isAstNonNullExpression(node) && !!node.data.questionDotToken; } + +/** @internal */ +export function isAstLeftHandSideExpression(node: AstNode): node is AstLeftHandSideExpression { + return isLeftHandSideExpressionKind(skipAstOuterExpressions(node, OuterExpressionKinds.PartiallyEmittedExpressions).kind); +} + +/** @internal */ +export function isAstStringOrNumericLiteralLike(node: AstNode): node is AstStringLiteralLike | AstNumericLiteral { + return isAstStringLiteralLike(node) || isAstNumericLiteral(node); +} + +/** @internal */ +export function isAstStringLiteralLike(node: AstNode): node is AstStringLiteralLike { + return node.kind === SyntaxKind.StringLiteral || node.kind === SyntaxKind.NoSubstitutionTemplateLiteral; +} + +/** + * True if has jsdoc nodes attached to it. + * + * @internal + */ +export function hasAstJSDocNodes(node: AstNode): node is AstHasJSDoc { + if (!canHaveJSDoc(node)) return false; + + const { data: { jsDoc } } = node; + return !!jsDoc && jsDoc.length > 0; +} diff --git a/src/compiler/forEachChild.ts b/src/compiler/forEachChild.ts new file mode 100644 index 00000000000..7c4b92a1428 --- /dev/null +++ b/src/compiler/forEachChild.ts @@ -0,0 +1,1018 @@ +import { + ArrayLiteralExpression, + ArrayTypeNode, + ArrowFunction, + AsExpression, + AwaitExpression, + BinaryExpression, + BindingElement, + BindingPattern, + Block, + BreakStatement, + CallExpression, + CallSignatureDeclaration, + CaseBlock, + CaseClause, + CatchClause, + ClassDeclaration, + ClassExpression, + ClassStaticBlockDeclaration, + CommaListExpression, + ComputedPropertyName, + ConditionalExpression, + ConditionalTypeNode, + ConstructorDeclaration, + ConstructorTypeNode, + ConstructSignatureDeclaration, + ContinueStatement, + Decorator, + DefaultClause, + DeleteExpression, + DoStatement, + ElementAccessExpression, + EnumDeclaration, + EnumMember, + ExportAssignment, + ExportDeclaration, + ExportSpecifier, + ExpressionStatement, + ExpressionWithTypeArguments, + ExternalModuleReference, + forEach, + ForEachChildNodes, + ForInStatement, + ForOfStatement, + ForStatement, + FunctionDeclaration, + FunctionExpression, + FunctionTypeNode, + GetAccessorDeclaration, + HeritageClause, + IfStatement, + ImportAttribute, + ImportAttributes, + ImportClause, + ImportDeclaration, + ImportEqualsDeclaration, + ImportSpecifier, + ImportTypeAssertionContainer, + ImportTypeNode, + IndexedAccessTypeNode, + IndexSignatureDeclaration, + InferTypeNode, + InterfaceDeclaration, + IntersectionTypeNode, + isArray, + JSDoc, + JSDocAugmentsTag, + JSDocAuthorTag, + JSDocCallbackTag, + JSDocClassTag, + JSDocDeprecatedTag, + JSDocEnumTag, + JSDocFunctionType, + JSDocImplementsTag, + JSDocImportTag, + JSDocLink, + JSDocLinkCode, + JSDocLinkPlain, + JSDocMemberName, + JSDocNameReference, + JSDocNonNullableType, + JSDocNullableType, + JSDocOptionalType, + JSDocOverloadTag, + JSDocOverrideTag, + JSDocParameterTag, + JSDocPrivateTag, + JSDocPropertyTag, + JSDocProtectedTag, + JSDocPublicTag, + JSDocReadonlyTag, + JSDocReturnTag, + JSDocSatisfiesTag, + JSDocSeeTag, + JSDocSignature, + JSDocTemplateTag, + JSDocThisTag, + JSDocThrowsTag, + JSDocTypedefTag, + JSDocTypeExpression, + JSDocTypeLiteral, + JSDocTypeTag, + JSDocUnknownTag, + JSDocVariadicType, + JsxAttribute, + JsxAttributes, + JsxClosingElement, + JsxElement, + JsxExpression, + JsxFragment, + JsxNamespacedName, + JsxOpeningLikeElement, + JsxSpreadAttribute, + LabeledStatement, + LiteralTypeNode, + MappedTypeNode, + MetaProperty, + MethodDeclaration, + MethodSignature, + MissingDeclaration, + ModuleBlock, + ModuleDeclaration, + NamedExports, + NamedImports, + NamedTupleMember, + NamespaceExport, + NamespaceExportDeclaration, + NamespaceImport, + NewExpression, + Node, + NodeArray, + NonNullExpression, + ObjectLiteralExpression, + OptionalTypeNode, + ParameterDeclaration, + ParenthesizedExpression, + ParenthesizedTypeNode, + PartiallyEmittedExpression, + PostfixUnaryExpression, + PrefixUnaryExpression, + PropertyAccessExpression, + PropertyAssignment, + PropertyDeclaration, + PropertySignature, + QualifiedName, + RestTypeNode, + ReturnStatement, + SatisfiesExpression, + SetAccessorDeclaration, + ShorthandPropertyAssignment, + SourceFile, + SpreadAssignment, + SpreadElement, + SwitchStatement, + SyntaxKind, + TaggedTemplateExpression, + TemplateExpression, + TemplateLiteralTypeNode, + TemplateLiteralTypeSpan, + TemplateSpan, + ThrowStatement, + TryStatement, + TupleTypeNode, + TypeAliasDeclaration, + TypeAssertion, + TypeLiteralNode, + TypeOfExpression, + TypeOperatorNode, + TypeParameterDeclaration, + TypePredicateNode, + TypeQueryNode, + TypeReferenceNode, + UnionTypeNode, + VariableDeclaration, + VariableDeclarationList, + VariableStatement, + VoidExpression, + WhileStatement, + WithStatement, + YieldExpression, +} from "./_namespaces/ts.js"; + +function visitNode(cbNode: (node: Node) => T, node: Node | undefined): T | undefined { + return node && cbNode(node); +} + +function visitNodes(cbNode: (node: Node) => T, cbNodes: ((node: NodeArray) => T | undefined) | undefined, nodes: NodeArray | undefined): T | undefined { + if (nodes) { + if (cbNodes) { + return cbNodes(nodes); + } + for (const node of nodes) { + const result = cbNode(node); + if (result) { + return result; + } + } + } +} + +type ForEachChildFunction = (node: TNode, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined) => T | undefined; +type ForEachChildTable = { [TNode in ForEachChildNodes as TNode["kind"]]: ForEachChildFunction; }; + +const forEachChildTable: ForEachChildTable = { + [SyntaxKind.QualifiedName]: function forEachChildInQualifiedName(node: QualifiedName, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { + return visitNode(cbNode, node.left) || + visitNode(cbNode, node.right); + }, + [SyntaxKind.TypeParameter]: function forEachChildInTypeParameter(node: TypeParameterDeclaration, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { + return visitNodes(cbNode, cbNodes, node.modifiers) || + visitNode(cbNode, node.name) || + visitNode(cbNode, node.constraint) || + visitNode(cbNode, node.default) || + visitNode(cbNode, node.expression); + }, + [SyntaxKind.ShorthandPropertyAssignment]: function forEachChildInShorthandPropertyAssignment(node: ShorthandPropertyAssignment, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { + return visitNodes(cbNode, cbNodes, node.modifiers) || + visitNode(cbNode, node.name) || + visitNode(cbNode, node.questionToken) || + visitNode(cbNode, node.exclamationToken) || + visitNode(cbNode, node.equalsToken) || + visitNode(cbNode, node.objectAssignmentInitializer); + }, + [SyntaxKind.SpreadAssignment]: function forEachChildInSpreadAssignment(node: SpreadAssignment, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { + return visitNode(cbNode, node.expression); + }, + [SyntaxKind.Parameter]: function forEachChildInParameter(node: ParameterDeclaration, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { + return visitNodes(cbNode, cbNodes, node.modifiers) || + visitNode(cbNode, node.dotDotDotToken) || + visitNode(cbNode, node.name) || + visitNode(cbNode, node.questionToken) || + visitNode(cbNode, node.type) || + visitNode(cbNode, node.initializer); + }, + [SyntaxKind.PropertyDeclaration]: function forEachChildInPropertyDeclaration(node: PropertyDeclaration, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { + return visitNodes(cbNode, cbNodes, node.modifiers) || + visitNode(cbNode, node.name) || + visitNode(cbNode, node.questionToken) || + visitNode(cbNode, node.exclamationToken) || + visitNode(cbNode, node.type) || + visitNode(cbNode, node.initializer); + }, + [SyntaxKind.PropertySignature]: function forEachChildInPropertySignature(node: PropertySignature, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { + return visitNodes(cbNode, cbNodes, node.modifiers) || + visitNode(cbNode, node.name) || + visitNode(cbNode, node.questionToken) || + visitNode(cbNode, node.type) || + visitNode(cbNode, node.initializer); + }, + [SyntaxKind.PropertyAssignment]: function forEachChildInPropertyAssignment(node: PropertyAssignment, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { + return visitNodes(cbNode, cbNodes, node.modifiers) || + visitNode(cbNode, node.name) || + visitNode(cbNode, node.questionToken) || + visitNode(cbNode, node.exclamationToken) || + visitNode(cbNode, node.initializer); + }, + [SyntaxKind.VariableDeclaration]: function forEachChildInVariableDeclaration(node: VariableDeclaration, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { + return visitNode(cbNode, node.name) || + visitNode(cbNode, node.exclamationToken) || + visitNode(cbNode, node.type) || + visitNode(cbNode, node.initializer); + }, + [SyntaxKind.BindingElement]: function forEachChildInBindingElement(node: BindingElement, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { + return visitNode(cbNode, node.dotDotDotToken) || + visitNode(cbNode, node.propertyName) || + visitNode(cbNode, node.name) || + visitNode(cbNode, node.initializer); + }, + [SyntaxKind.IndexSignature]: function forEachChildInIndexSignature(node: IndexSignatureDeclaration, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { + return visitNodes(cbNode, cbNodes, node.modifiers) || + visitNodes(cbNode, cbNodes, node.typeParameters) || + visitNodes(cbNode, cbNodes, node.parameters) || + visitNode(cbNode, node.type); + }, + [SyntaxKind.ConstructorType]: function forEachChildInConstructorType(node: ConstructorTypeNode, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { + return visitNodes(cbNode, cbNodes, node.modifiers) || + visitNodes(cbNode, cbNodes, node.typeParameters) || + visitNodes(cbNode, cbNodes, node.parameters) || + visitNode(cbNode, node.type); + }, + [SyntaxKind.FunctionType]: function forEachChildInFunctionType(node: FunctionTypeNode, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { + return visitNodes(cbNode, cbNodes, node.modifiers) || + visitNodes(cbNode, cbNodes, node.typeParameters) || + visitNodes(cbNode, cbNodes, node.parameters) || + visitNode(cbNode, node.type); + }, + [SyntaxKind.CallSignature]: forEachChildInCallOrConstructSignature, + [SyntaxKind.ConstructSignature]: forEachChildInCallOrConstructSignature, + [SyntaxKind.MethodDeclaration]: function forEachChildInMethodDeclaration(node: MethodDeclaration, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { + return visitNodes(cbNode, cbNodes, node.modifiers) || + visitNode(cbNode, node.asteriskToken) || + visitNode(cbNode, node.name) || + visitNode(cbNode, node.questionToken) || + visitNode(cbNode, node.exclamationToken) || + visitNodes(cbNode, cbNodes, node.typeParameters) || + visitNodes(cbNode, cbNodes, node.parameters) || + visitNode(cbNode, node.type) || + visitNode(cbNode, node.body); + }, + [SyntaxKind.MethodSignature]: function forEachChildInMethodSignature(node: MethodSignature, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { + return visitNodes(cbNode, cbNodes, node.modifiers) || + visitNode(cbNode, node.name) || + visitNode(cbNode, node.questionToken) || + visitNodes(cbNode, cbNodes, node.typeParameters) || + visitNodes(cbNode, cbNodes, node.parameters) || + visitNode(cbNode, node.type); + }, + [SyntaxKind.Constructor]: function forEachChildInConstructor(node: ConstructorDeclaration, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { + return visitNodes(cbNode, cbNodes, node.modifiers) || + visitNode(cbNode, node.name) || + visitNodes(cbNode, cbNodes, node.typeParameters) || + visitNodes(cbNode, cbNodes, node.parameters) || + visitNode(cbNode, node.type) || + visitNode(cbNode, node.body); + }, + [SyntaxKind.GetAccessor]: function forEachChildInGetAccessor(node: GetAccessorDeclaration, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { + return visitNodes(cbNode, cbNodes, node.modifiers) || + visitNode(cbNode, node.name) || + visitNodes(cbNode, cbNodes, node.typeParameters) || + visitNodes(cbNode, cbNodes, node.parameters) || + visitNode(cbNode, node.type) || + visitNode(cbNode, node.body); + }, + [SyntaxKind.SetAccessor]: function forEachChildInSetAccessor(node: SetAccessorDeclaration, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { + return visitNodes(cbNode, cbNodes, node.modifiers) || + visitNode(cbNode, node.name) || + visitNodes(cbNode, cbNodes, node.typeParameters) || + visitNodes(cbNode, cbNodes, node.parameters) || + visitNode(cbNode, node.type) || + visitNode(cbNode, node.body); + }, + [SyntaxKind.FunctionDeclaration]: function forEachChildInFunctionDeclaration(node: FunctionDeclaration, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { + return visitNodes(cbNode, cbNodes, node.modifiers) || + visitNode(cbNode, node.asteriskToken) || + visitNode(cbNode, node.name) || + visitNodes(cbNode, cbNodes, node.typeParameters) || + visitNodes(cbNode, cbNodes, node.parameters) || + visitNode(cbNode, node.type) || + visitNode(cbNode, node.body); + }, + [SyntaxKind.FunctionExpression]: function forEachChildInFunctionExpression(node: FunctionExpression, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { + return visitNodes(cbNode, cbNodes, node.modifiers) || + visitNode(cbNode, node.asteriskToken) || + visitNode(cbNode, node.name) || + visitNodes(cbNode, cbNodes, node.typeParameters) || + visitNodes(cbNode, cbNodes, node.parameters) || + visitNode(cbNode, node.type) || + visitNode(cbNode, node.body); + }, + [SyntaxKind.ArrowFunction]: function forEachChildInArrowFunction(node: ArrowFunction, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { + return visitNodes(cbNode, cbNodes, node.modifiers) || + visitNodes(cbNode, cbNodes, node.typeParameters) || + visitNodes(cbNode, cbNodes, node.parameters) || + visitNode(cbNode, node.type) || + visitNode(cbNode, node.equalsGreaterThanToken) || + visitNode(cbNode, node.body); + }, + [SyntaxKind.ClassStaticBlockDeclaration]: function forEachChildInClassStaticBlockDeclaration(node: ClassStaticBlockDeclaration, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { + return visitNodes(cbNode, cbNodes, node.modifiers) || + visitNode(cbNode, node.body); + }, + [SyntaxKind.TypeReference]: function forEachChildInTypeReference(node: TypeReferenceNode, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { + return visitNode(cbNode, node.typeName) || + visitNodes(cbNode, cbNodes, node.typeArguments); + }, + [SyntaxKind.TypePredicate]: function forEachChildInTypePredicate(node: TypePredicateNode, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { + return visitNode(cbNode, node.assertsModifier) || + visitNode(cbNode, node.parameterName) || + visitNode(cbNode, node.type); + }, + [SyntaxKind.TypeQuery]: function forEachChildInTypeQuery(node: TypeQueryNode, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { + return visitNode(cbNode, node.exprName) || + visitNodes(cbNode, cbNodes, node.typeArguments); + }, + [SyntaxKind.TypeLiteral]: function forEachChildInTypeLiteral(node: TypeLiteralNode, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { + return visitNodes(cbNode, cbNodes, node.members); + }, + [SyntaxKind.ArrayType]: function forEachChildInArrayType(node: ArrayTypeNode, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { + return visitNode(cbNode, node.elementType); + }, + [SyntaxKind.TupleType]: function forEachChildInTupleType(node: TupleTypeNode, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { + return visitNodes(cbNode, cbNodes, node.elements); + }, + [SyntaxKind.UnionType]: forEachChildInUnionOrIntersectionType, + [SyntaxKind.IntersectionType]: forEachChildInUnionOrIntersectionType, + [SyntaxKind.ConditionalType]: function forEachChildInConditionalType(node: ConditionalTypeNode, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { + return visitNode(cbNode, node.checkType) || + visitNode(cbNode, node.extendsType) || + visitNode(cbNode, node.trueType) || + visitNode(cbNode, node.falseType); + }, + [SyntaxKind.InferType]: function forEachChildInInferType(node: InferTypeNode, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { + return visitNode(cbNode, node.typeParameter); + }, + [SyntaxKind.ImportType]: function forEachChildInImportType(node: ImportTypeNode, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { + return visitNode(cbNode, node.argument) || + visitNode(cbNode, node.attributes) || + visitNode(cbNode, node.qualifier) || + visitNodes(cbNode, cbNodes, node.typeArguments); + }, + [SyntaxKind.ImportTypeAssertionContainer]: function forEachChildInImportTypeAssertionContainer(node: ImportTypeAssertionContainer, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { + return visitNode(cbNode, node.assertClause); + }, + [SyntaxKind.ParenthesizedType]: forEachChildInParenthesizedTypeOrTypeOperator, + [SyntaxKind.TypeOperator]: forEachChildInParenthesizedTypeOrTypeOperator, + [SyntaxKind.IndexedAccessType]: function forEachChildInIndexedAccessType(node: IndexedAccessTypeNode, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { + return visitNode(cbNode, node.objectType) || + visitNode(cbNode, node.indexType); + }, + [SyntaxKind.MappedType]: function forEachChildInMappedType(node: MappedTypeNode, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { + return visitNode(cbNode, node.readonlyToken) || + visitNode(cbNode, node.typeParameter) || + visitNode(cbNode, node.nameType) || + visitNode(cbNode, node.questionToken) || + visitNode(cbNode, node.type) || + visitNodes(cbNode, cbNodes, node.members); + }, + [SyntaxKind.LiteralType]: function forEachChildInLiteralType(node: LiteralTypeNode, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { + return visitNode(cbNode, node.literal); + }, + [SyntaxKind.NamedTupleMember]: function forEachChildInNamedTupleMember(node: NamedTupleMember, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { + return visitNode(cbNode, node.dotDotDotToken) || + visitNode(cbNode, node.name) || + visitNode(cbNode, node.questionToken) || + visitNode(cbNode, node.type); + }, + [SyntaxKind.ObjectBindingPattern]: forEachChildInObjectOrArrayBindingPattern, + [SyntaxKind.ArrayBindingPattern]: forEachChildInObjectOrArrayBindingPattern, + [SyntaxKind.ArrayLiteralExpression]: function forEachChildInArrayLiteralExpression(node: ArrayLiteralExpression, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { + return visitNodes(cbNode, cbNodes, node.elements); + }, + [SyntaxKind.ObjectLiteralExpression]: function forEachChildInObjectLiteralExpression(node: ObjectLiteralExpression, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { + return visitNodes(cbNode, cbNodes, node.properties); + }, + [SyntaxKind.PropertyAccessExpression]: function forEachChildInPropertyAccessExpression(node: PropertyAccessExpression, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { + return visitNode(cbNode, node.expression) || + visitNode(cbNode, node.questionDotToken) || + visitNode(cbNode, node.name); + }, + [SyntaxKind.ElementAccessExpression]: function forEachChildInElementAccessExpression(node: ElementAccessExpression, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { + return visitNode(cbNode, node.expression) || + visitNode(cbNode, node.questionDotToken) || + visitNode(cbNode, node.argumentExpression); + }, + [SyntaxKind.CallExpression]: forEachChildInCallOrNewExpression, + [SyntaxKind.NewExpression]: forEachChildInCallOrNewExpression, + [SyntaxKind.TaggedTemplateExpression]: function forEachChildInTaggedTemplateExpression(node: TaggedTemplateExpression, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { + return visitNode(cbNode, node.tag) || + visitNode(cbNode, node.questionDotToken) || + visitNodes(cbNode, cbNodes, node.typeArguments) || + visitNode(cbNode, node.template); + }, + [SyntaxKind.TypeAssertionExpression]: function forEachChildInTypeAssertionExpression(node: TypeAssertion, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { + return visitNode(cbNode, node.type) || + visitNode(cbNode, node.expression); + }, + [SyntaxKind.ParenthesizedExpression]: function forEachChildInParenthesizedExpression(node: ParenthesizedExpression, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { + return visitNode(cbNode, node.expression); + }, + [SyntaxKind.DeleteExpression]: function forEachChildInDeleteExpression(node: DeleteExpression, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { + return visitNode(cbNode, node.expression); + }, + [SyntaxKind.TypeOfExpression]: function forEachChildInTypeOfExpression(node: TypeOfExpression, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { + return visitNode(cbNode, node.expression); + }, + [SyntaxKind.VoidExpression]: function forEachChildInVoidExpression(node: VoidExpression, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { + return visitNode(cbNode, node.expression); + }, + [SyntaxKind.PrefixUnaryExpression]: function forEachChildInPrefixUnaryExpression(node: PrefixUnaryExpression, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { + return visitNode(cbNode, node.operand); + }, + [SyntaxKind.YieldExpression]: function forEachChildInYieldExpression(node: YieldExpression, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { + return visitNode(cbNode, node.asteriskToken) || + visitNode(cbNode, node.expression); + }, + [SyntaxKind.AwaitExpression]: function forEachChildInAwaitExpression(node: AwaitExpression, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { + return visitNode(cbNode, node.expression); + }, + [SyntaxKind.PostfixUnaryExpression]: function forEachChildInPostfixUnaryExpression(node: PostfixUnaryExpression, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { + return visitNode(cbNode, node.operand); + }, + [SyntaxKind.BinaryExpression]: function forEachChildInBinaryExpression(node: BinaryExpression, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { + return visitNode(cbNode, node.left) || + visitNode(cbNode, node.operatorToken) || + visitNode(cbNode, node.right); + }, + [SyntaxKind.AsExpression]: function forEachChildInAsExpression(node: AsExpression, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { + return visitNode(cbNode, node.expression) || + visitNode(cbNode, node.type); + }, + [SyntaxKind.NonNullExpression]: function forEachChildInNonNullExpression(node: NonNullExpression, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { + return visitNode(cbNode, node.expression); + }, + [SyntaxKind.SatisfiesExpression]: function forEachChildInSatisfiesExpression(node: SatisfiesExpression, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { + return visitNode(cbNode, node.expression) || visitNode(cbNode, node.type); + }, + [SyntaxKind.MetaProperty]: function forEachChildInMetaProperty(node: MetaProperty, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { + return visitNode(cbNode, node.name); + }, + [SyntaxKind.ConditionalExpression]: function forEachChildInConditionalExpression(node: ConditionalExpression, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { + return visitNode(cbNode, node.condition) || + visitNode(cbNode, node.questionToken) || + visitNode(cbNode, node.whenTrue) || + visitNode(cbNode, node.colonToken) || + visitNode(cbNode, node.whenFalse); + }, + [SyntaxKind.SpreadElement]: function forEachChildInSpreadElement(node: SpreadElement, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { + return visitNode(cbNode, node.expression); + }, + [SyntaxKind.Block]: forEachChildInBlock, + [SyntaxKind.ModuleBlock]: forEachChildInBlock, + [SyntaxKind.SourceFile]: function forEachChildInSourceFile(node: SourceFile, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { + return visitNodes(cbNode, cbNodes, node.statements) || + visitNode(cbNode, node.endOfFileToken); + }, + [SyntaxKind.VariableStatement]: function forEachChildInVariableStatement(node: VariableStatement, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { + return visitNodes(cbNode, cbNodes, node.modifiers) || + visitNode(cbNode, node.declarationList); + }, + [SyntaxKind.VariableDeclarationList]: function forEachChildInVariableDeclarationList(node: VariableDeclarationList, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { + return visitNodes(cbNode, cbNodes, node.declarations); + }, + [SyntaxKind.ExpressionStatement]: function forEachChildInExpressionStatement(node: ExpressionStatement, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { + return visitNode(cbNode, node.expression); + }, + [SyntaxKind.IfStatement]: function forEachChildInIfStatement(node: IfStatement, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { + return visitNode(cbNode, node.expression) || + visitNode(cbNode, node.thenStatement) || + visitNode(cbNode, node.elseStatement); + }, + [SyntaxKind.DoStatement]: function forEachChildInDoStatement(node: DoStatement, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { + return visitNode(cbNode, node.statement) || + visitNode(cbNode, node.expression); + }, + [SyntaxKind.WhileStatement]: function forEachChildInWhileStatement(node: WhileStatement, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { + return visitNode(cbNode, node.expression) || + visitNode(cbNode, node.statement); + }, + [SyntaxKind.ForStatement]: function forEachChildInForStatement(node: ForStatement, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { + return visitNode(cbNode, node.initializer) || + visitNode(cbNode, node.condition) || + visitNode(cbNode, node.incrementor) || + visitNode(cbNode, node.statement); + }, + [SyntaxKind.ForInStatement]: function forEachChildInForInStatement(node: ForInStatement, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { + return visitNode(cbNode, node.initializer) || + visitNode(cbNode, node.expression) || + visitNode(cbNode, node.statement); + }, + [SyntaxKind.ForOfStatement]: function forEachChildInForOfStatement(node: ForOfStatement, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { + return visitNode(cbNode, node.awaitModifier) || + visitNode(cbNode, node.initializer) || + visitNode(cbNode, node.expression) || + visitNode(cbNode, node.statement); + }, + [SyntaxKind.ContinueStatement]: forEachChildInContinueOrBreakStatement, + [SyntaxKind.BreakStatement]: forEachChildInContinueOrBreakStatement, + [SyntaxKind.ReturnStatement]: function forEachChildInReturnStatement(node: ReturnStatement, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { + return visitNode(cbNode, node.expression); + }, + [SyntaxKind.WithStatement]: function forEachChildInWithStatement(node: WithStatement, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { + return visitNode(cbNode, node.expression) || + visitNode(cbNode, node.statement); + }, + [SyntaxKind.SwitchStatement]: function forEachChildInSwitchStatement(node: SwitchStatement, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { + return visitNode(cbNode, node.expression) || + visitNode(cbNode, node.caseBlock); + }, + [SyntaxKind.CaseBlock]: function forEachChildInCaseBlock(node: CaseBlock, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { + return visitNodes(cbNode, cbNodes, node.clauses); + }, + [SyntaxKind.CaseClause]: function forEachChildInCaseClause(node: CaseClause, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { + return visitNode(cbNode, node.expression) || + visitNodes(cbNode, cbNodes, node.statements); + }, + [SyntaxKind.DefaultClause]: function forEachChildInDefaultClause(node: DefaultClause, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { + return visitNodes(cbNode, cbNodes, node.statements); + }, + [SyntaxKind.LabeledStatement]: function forEachChildInLabeledStatement(node: LabeledStatement, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { + return visitNode(cbNode, node.label) || + visitNode(cbNode, node.statement); + }, + [SyntaxKind.ThrowStatement]: function forEachChildInThrowStatement(node: ThrowStatement, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { + return visitNode(cbNode, node.expression); + }, + [SyntaxKind.TryStatement]: function forEachChildInTryStatement(node: TryStatement, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { + return visitNode(cbNode, node.tryBlock) || + visitNode(cbNode, node.catchClause) || + visitNode(cbNode, node.finallyBlock); + }, + [SyntaxKind.CatchClause]: function forEachChildInCatchClause(node: CatchClause, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { + return visitNode(cbNode, node.variableDeclaration) || + visitNode(cbNode, node.block); + }, + [SyntaxKind.Decorator]: function forEachChildInDecorator(node: Decorator, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { + return visitNode(cbNode, node.expression); + }, + [SyntaxKind.ClassDeclaration]: forEachChildInClassDeclarationOrExpression, + [SyntaxKind.ClassExpression]: forEachChildInClassDeclarationOrExpression, + [SyntaxKind.InterfaceDeclaration]: function forEachChildInInterfaceDeclaration(node: InterfaceDeclaration, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { + return visitNodes(cbNode, cbNodes, node.modifiers) || + visitNode(cbNode, node.name) || + visitNodes(cbNode, cbNodes, node.typeParameters) || + visitNodes(cbNode, cbNodes, node.heritageClauses) || + visitNodes(cbNode, cbNodes, node.members); + }, + [SyntaxKind.TypeAliasDeclaration]: function forEachChildInTypeAliasDeclaration(node: TypeAliasDeclaration, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { + return visitNodes(cbNode, cbNodes, node.modifiers) || + visitNode(cbNode, node.name) || + visitNodes(cbNode, cbNodes, node.typeParameters) || + visitNode(cbNode, node.type); + }, + [SyntaxKind.EnumDeclaration]: function forEachChildInEnumDeclaration(node: EnumDeclaration, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { + return visitNodes(cbNode, cbNodes, node.modifiers) || + visitNode(cbNode, node.name) || + visitNodes(cbNode, cbNodes, node.members); + }, + [SyntaxKind.EnumMember]: function forEachChildInEnumMember(node: EnumMember, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { + return visitNode(cbNode, node.name) || + visitNode(cbNode, node.initializer); + }, + [SyntaxKind.ModuleDeclaration]: function forEachChildInModuleDeclaration(node: ModuleDeclaration, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { + return visitNodes(cbNode, cbNodes, node.modifiers) || + visitNode(cbNode, node.name) || + visitNode(cbNode, node.body); + }, + [SyntaxKind.ImportEqualsDeclaration]: function forEachChildInImportEqualsDeclaration(node: ImportEqualsDeclaration, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { + return visitNodes(cbNode, cbNodes, node.modifiers) || + visitNode(cbNode, node.name) || + visitNode(cbNode, node.moduleReference); + }, + [SyntaxKind.ImportDeclaration]: function forEachChildInImportDeclaration(node: ImportDeclaration, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { + return visitNodes(cbNode, cbNodes, node.modifiers) || + visitNode(cbNode, node.importClause) || + visitNode(cbNode, node.moduleSpecifier) || + visitNode(cbNode, node.attributes); + }, + [SyntaxKind.ImportClause]: function forEachChildInImportClause(node: ImportClause, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { + return visitNode(cbNode, node.name) || + visitNode(cbNode, node.namedBindings); + }, + [SyntaxKind.ImportAttributes]: function forEachChildInImportAttributes(node: ImportAttributes, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { + return visitNodes(cbNode, cbNodes, node.elements); + }, + [SyntaxKind.ImportAttribute]: function forEachChildInImportAttribute(node: ImportAttribute, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { + return visitNode(cbNode, node.name) || + visitNode(cbNode, node.value); + }, + [SyntaxKind.NamespaceExportDeclaration]: function forEachChildInNamespaceExportDeclaration(node: NamespaceExportDeclaration, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { + return visitNodes(cbNode, cbNodes, node.modifiers) || + visitNode(cbNode, node.name); + }, + [SyntaxKind.NamespaceImport]: function forEachChildInNamespaceImport(node: NamespaceImport, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { + return visitNode(cbNode, node.name); + }, + [SyntaxKind.NamespaceExport]: function forEachChildInNamespaceExport(node: NamespaceExport, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { + return visitNode(cbNode, node.name); + }, + [SyntaxKind.NamedImports]: forEachChildInNamedImportsOrExports, + [SyntaxKind.NamedExports]: forEachChildInNamedImportsOrExports, + [SyntaxKind.ExportDeclaration]: function forEachChildInExportDeclaration(node: ExportDeclaration, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { + return visitNodes(cbNode, cbNodes, node.modifiers) || + visitNode(cbNode, node.exportClause) || + visitNode(cbNode, node.moduleSpecifier) || + visitNode(cbNode, node.attributes); + }, + [SyntaxKind.ImportSpecifier]: forEachChildInImportOrExportSpecifier, + [SyntaxKind.ExportSpecifier]: forEachChildInImportOrExportSpecifier, + [SyntaxKind.ExportAssignment]: function forEachChildInExportAssignment(node: ExportAssignment, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { + return visitNodes(cbNode, cbNodes, node.modifiers) || + visitNode(cbNode, node.expression); + }, + [SyntaxKind.TemplateExpression]: function forEachChildInTemplateExpression(node: TemplateExpression, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { + return visitNode(cbNode, node.head) || + visitNodes(cbNode, cbNodes, node.templateSpans); + }, + [SyntaxKind.TemplateSpan]: function forEachChildInTemplateSpan(node: TemplateSpan, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { + return visitNode(cbNode, node.expression) || + visitNode(cbNode, node.literal); + }, + [SyntaxKind.TemplateLiteralType]: function forEachChildInTemplateLiteralType(node: TemplateLiteralTypeNode, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { + return visitNode(cbNode, node.head) || + visitNodes(cbNode, cbNodes, node.templateSpans); + }, + [SyntaxKind.TemplateLiteralTypeSpan]: function forEachChildInTemplateLiteralTypeSpan(node: TemplateLiteralTypeSpan, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { + return visitNode(cbNode, node.type) || + visitNode(cbNode, node.literal); + }, + [SyntaxKind.ComputedPropertyName]: function forEachChildInComputedPropertyName(node: ComputedPropertyName, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { + return visitNode(cbNode, node.expression); + }, + [SyntaxKind.HeritageClause]: function forEachChildInHeritageClause(node: HeritageClause, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { + return visitNodes(cbNode, cbNodes, node.types); + }, + [SyntaxKind.ExpressionWithTypeArguments]: function forEachChildInExpressionWithTypeArguments(node: ExpressionWithTypeArguments, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { + return visitNode(cbNode, node.expression) || + visitNodes(cbNode, cbNodes, node.typeArguments); + }, + [SyntaxKind.ExternalModuleReference]: function forEachChildInExternalModuleReference(node: ExternalModuleReference, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { + return visitNode(cbNode, node.expression); + }, + [SyntaxKind.MissingDeclaration]: function forEachChildInMissingDeclaration(node: MissingDeclaration, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { + return visitNodes(cbNode, cbNodes, node.modifiers); + }, + [SyntaxKind.CommaListExpression]: function forEachChildInCommaListExpression(node: CommaListExpression, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { + return visitNodes(cbNode, cbNodes, node.elements); + }, + [SyntaxKind.JsxElement]: function forEachChildInJsxElement(node: JsxElement, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { + return visitNode(cbNode, node.openingElement) || + visitNodes(cbNode, cbNodes, node.children) || + visitNode(cbNode, node.closingElement); + }, + [SyntaxKind.JsxFragment]: function forEachChildInJsxFragment(node: JsxFragment, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { + return visitNode(cbNode, node.openingFragment) || + visitNodes(cbNode, cbNodes, node.children) || + visitNode(cbNode, node.closingFragment); + }, + [SyntaxKind.JsxSelfClosingElement]: forEachChildInJsxOpeningOrSelfClosingElement, + [SyntaxKind.JsxOpeningElement]: forEachChildInJsxOpeningOrSelfClosingElement, + [SyntaxKind.JsxAttributes]: function forEachChildInJsxAttributes(node: JsxAttributes, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { + return visitNodes(cbNode, cbNodes, node.properties); + }, + [SyntaxKind.JsxAttribute]: function forEachChildInJsxAttribute(node: JsxAttribute, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { + return visitNode(cbNode, node.name) || + visitNode(cbNode, node.initializer); + }, + [SyntaxKind.JsxSpreadAttribute]: function forEachChildInJsxSpreadAttribute(node: JsxSpreadAttribute, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { + return visitNode(cbNode, node.expression); + }, + [SyntaxKind.JsxExpression]: function forEachChildInJsxExpression(node: JsxExpression, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { + return visitNode(cbNode, node.dotDotDotToken) || + visitNode(cbNode, node.expression); + }, + [SyntaxKind.JsxClosingElement]: function forEachChildInJsxClosingElement(node: JsxClosingElement, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { + return visitNode(cbNode, node.tagName); + }, + [SyntaxKind.JsxNamespacedName]: function forEachChildInJsxNamespacedName(node: JsxNamespacedName, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { + return visitNode(cbNode, node.namespace) || + visitNode(cbNode, node.name); + }, + [SyntaxKind.OptionalType]: forEachChildInOptionalRestOrJSDocParameterModifier, + [SyntaxKind.RestType]: forEachChildInOptionalRestOrJSDocParameterModifier, + [SyntaxKind.JSDocTypeExpression]: forEachChildInOptionalRestOrJSDocParameterModifier, + [SyntaxKind.JSDocNonNullableType]: forEachChildInOptionalRestOrJSDocParameterModifier, + [SyntaxKind.JSDocNullableType]: forEachChildInOptionalRestOrJSDocParameterModifier, + [SyntaxKind.JSDocOptionalType]: forEachChildInOptionalRestOrJSDocParameterModifier, + [SyntaxKind.JSDocVariadicType]: forEachChildInOptionalRestOrJSDocParameterModifier, + [SyntaxKind.JSDocFunctionType]: function forEachChildInJSDocFunctionType(node: JSDocFunctionType, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { + return visitNodes(cbNode, cbNodes, node.parameters) || + visitNode(cbNode, node.type); + }, + [SyntaxKind.JSDoc]: function forEachChildInJSDoc(node: JSDoc, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { + return (typeof node.comment === "string" ? undefined : visitNodes(cbNode, cbNodes, node.comment)) + || visitNodes(cbNode, cbNodes, node.tags); + }, + [SyntaxKind.JSDocSeeTag]: function forEachChildInJSDocSeeTag(node: JSDocSeeTag, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { + return visitNode(cbNode, node.tagName) || + visitNode(cbNode, node.name) || + (typeof node.comment === "string" ? undefined : visitNodes(cbNode, cbNodes, node.comment)); + }, + [SyntaxKind.JSDocNameReference]: function forEachChildInJSDocNameReference(node: JSDocNameReference, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { + return visitNode(cbNode, node.name); + }, + [SyntaxKind.JSDocMemberName]: function forEachChildInJSDocMemberName(node: JSDocMemberName, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { + return visitNode(cbNode, node.left) || + visitNode(cbNode, node.right); + }, + [SyntaxKind.JSDocParameterTag]: forEachChildInJSDocParameterOrPropertyTag, + [SyntaxKind.JSDocPropertyTag]: forEachChildInJSDocParameterOrPropertyTag, + [SyntaxKind.JSDocAuthorTag]: function forEachChildInJSDocAuthorTag(node: JSDocAuthorTag, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { + return visitNode(cbNode, node.tagName) || + (typeof node.comment === "string" ? undefined : visitNodes(cbNode, cbNodes, node.comment)); + }, + [SyntaxKind.JSDocImplementsTag]: function forEachChildInJSDocImplementsTag(node: JSDocImplementsTag, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { + return visitNode(cbNode, node.tagName) || + visitNode(cbNode, node.class) || + (typeof node.comment === "string" ? undefined : visitNodes(cbNode, cbNodes, node.comment)); + }, + [SyntaxKind.JSDocAugmentsTag]: function forEachChildInJSDocAugmentsTag(node: JSDocAugmentsTag, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { + return visitNode(cbNode, node.tagName) || + visitNode(cbNode, node.class) || + (typeof node.comment === "string" ? undefined : visitNodes(cbNode, cbNodes, node.comment)); + }, + [SyntaxKind.JSDocTemplateTag]: function forEachChildInJSDocTemplateTag(node: JSDocTemplateTag, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { + return visitNode(cbNode, node.tagName) || + visitNode(cbNode, node.constraint) || + visitNodes(cbNode, cbNodes, node.typeParameters) || + (typeof node.comment === "string" ? undefined : visitNodes(cbNode, cbNodes, node.comment)); + }, + [SyntaxKind.JSDocTypedefTag]: function forEachChildInJSDocTypedefTag(node: JSDocTypedefTag, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { + return visitNode(cbNode, node.tagName) || + (node.typeExpression && + node.typeExpression.kind === SyntaxKind.JSDocTypeExpression + ? visitNode(cbNode, node.typeExpression) || + visitNode(cbNode, node.fullName) || + (typeof node.comment === "string" ? undefined : visitNodes(cbNode, cbNodes, node.comment)) + : visitNode(cbNode, node.fullName) || + visitNode(cbNode, node.typeExpression) || + (typeof node.comment === "string" ? undefined : visitNodes(cbNode, cbNodes, node.comment))); + }, + [SyntaxKind.JSDocCallbackTag]: function forEachChildInJSDocCallbackTag(node: JSDocCallbackTag, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { + return visitNode(cbNode, node.tagName) || + visitNode(cbNode, node.fullName) || + visitNode(cbNode, node.typeExpression) || + (typeof node.comment === "string" ? undefined : visitNodes(cbNode, cbNodes, node.comment)); + }, + [SyntaxKind.JSDocReturnTag]: forEachChildInJSDocTypeLikeTag, + [SyntaxKind.JSDocTypeTag]: forEachChildInJSDocTypeLikeTag, + [SyntaxKind.JSDocThisTag]: forEachChildInJSDocTypeLikeTag, + [SyntaxKind.JSDocEnumTag]: forEachChildInJSDocTypeLikeTag, + [SyntaxKind.JSDocSatisfiesTag]: forEachChildInJSDocTypeLikeTag, + [SyntaxKind.JSDocThrowsTag]: forEachChildInJSDocTypeLikeTag, + [SyntaxKind.JSDocOverloadTag]: forEachChildInJSDocTypeLikeTag, + [SyntaxKind.JSDocSignature]: function forEachChildInJSDocSignature(node: JSDocSignature, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { + return forEach(node.typeParameters, cbNode) || + forEach(node.parameters, cbNode) || + visitNode(cbNode, node.type); + }, + [SyntaxKind.JSDocLink]: forEachChildInJSDocLinkCodeOrPlain, + [SyntaxKind.JSDocLinkCode]: forEachChildInJSDocLinkCodeOrPlain, + [SyntaxKind.JSDocLinkPlain]: forEachChildInJSDocLinkCodeOrPlain, + [SyntaxKind.JSDocTypeLiteral]: function forEachChildInJSDocTypeLiteral(node: JSDocTypeLiteral, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { + return forEach(node.jsDocPropertyTags, cbNode); + }, + [SyntaxKind.JSDocTag]: forEachChildInJSDocTag, + [SyntaxKind.JSDocClassTag]: forEachChildInJSDocTag, + [SyntaxKind.JSDocPublicTag]: forEachChildInJSDocTag, + [SyntaxKind.JSDocPrivateTag]: forEachChildInJSDocTag, + [SyntaxKind.JSDocProtectedTag]: forEachChildInJSDocTag, + [SyntaxKind.JSDocReadonlyTag]: forEachChildInJSDocTag, + [SyntaxKind.JSDocDeprecatedTag]: forEachChildInJSDocTag, + [SyntaxKind.JSDocOverrideTag]: forEachChildInJSDocTag, + [SyntaxKind.JSDocImportTag]: forEachChildInJSDocImportTag, + [SyntaxKind.PartiallyEmittedExpression]: forEachChildInPartiallyEmittedExpression, +}; + +// shared + +function forEachChildInCallOrConstructSignature(node: CallSignatureDeclaration | ConstructSignatureDeclaration, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { + return visitNodes(cbNode, cbNodes, node.typeParameters) || + visitNodes(cbNode, cbNodes, node.parameters) || + visitNode(cbNode, node.type); +} + +function forEachChildInUnionOrIntersectionType(node: UnionTypeNode | IntersectionTypeNode, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { + return visitNodes(cbNode, cbNodes, node.types); +} + +function forEachChildInParenthesizedTypeOrTypeOperator(node: ParenthesizedTypeNode | TypeOperatorNode, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { + return visitNode(cbNode, node.type); +} + +function forEachChildInObjectOrArrayBindingPattern(node: BindingPattern, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { + return visitNodes(cbNode, cbNodes, node.elements); +} + +function forEachChildInCallOrNewExpression(node: CallExpression | NewExpression, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { + return visitNode(cbNode, node.expression) || + // TODO: should we separate these branches out? + visitNode(cbNode, (node as CallExpression).questionDotToken) || + visitNodes(cbNode, cbNodes, node.typeArguments) || + visitNodes(cbNode, cbNodes, node.arguments); +} + +function forEachChildInBlock(node: Block | ModuleBlock, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { + return visitNodes(cbNode, cbNodes, node.statements); +} + +function forEachChildInContinueOrBreakStatement(node: ContinueStatement | BreakStatement, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { + return visitNode(cbNode, node.label); +} + +function forEachChildInClassDeclarationOrExpression(node: ClassDeclaration | ClassExpression, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { + return visitNodes(cbNode, cbNodes, node.modifiers) || + visitNode(cbNode, node.name) || + visitNodes(cbNode, cbNodes, node.typeParameters) || + visitNodes(cbNode, cbNodes, node.heritageClauses) || + visitNodes(cbNode, cbNodes, node.members); +} + +function forEachChildInNamedImportsOrExports(node: NamedImports | NamedExports, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { + return visitNodes(cbNode, cbNodes, node.elements); +} + +function forEachChildInImportOrExportSpecifier(node: ImportSpecifier | ExportSpecifier, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { + return visitNode(cbNode, node.propertyName) || + visitNode(cbNode, node.name); +} + +function forEachChildInJsxOpeningOrSelfClosingElement(node: JsxOpeningLikeElement, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { + return visitNode(cbNode, node.tagName) || + visitNodes(cbNode, cbNodes, node.typeArguments) || + visitNode(cbNode, node.attributes); +} + +function forEachChildInOptionalRestOrJSDocParameterModifier(node: OptionalTypeNode | RestTypeNode | JSDocTypeExpression | JSDocNullableType | JSDocNonNullableType | JSDocOptionalType | JSDocVariadicType, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { + return visitNode(cbNode, node.type); +} + +function forEachChildInJSDocParameterOrPropertyTag(node: JSDocParameterTag | JSDocPropertyTag, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { + return visitNode(cbNode, node.tagName) || + (node.isNameFirst + ? visitNode(cbNode, node.name) || visitNode(cbNode, node.typeExpression) + : visitNode(cbNode, node.typeExpression) || visitNode(cbNode, node.name)) || + (typeof node.comment === "string" ? undefined : visitNodes(cbNode, cbNodes, node.comment)); +} + +function forEachChildInJSDocTypeLikeTag(node: JSDocReturnTag | JSDocTypeTag | JSDocThisTag | JSDocEnumTag | JSDocThrowsTag | JSDocOverloadTag | JSDocSatisfiesTag, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { + return visitNode(cbNode, node.tagName) || + visitNode(cbNode, node.typeExpression) || + (typeof node.comment === "string" ? undefined : visitNodes(cbNode, cbNodes, node.comment)); +} + +function forEachChildInJSDocLinkCodeOrPlain(node: JSDocLink | JSDocLinkCode | JSDocLinkPlain, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { + return visitNode(cbNode, node.name); +} + +function forEachChildInJSDocTag(node: JSDocUnknownTag | JSDocClassTag | JSDocPublicTag | JSDocPrivateTag | JSDocProtectedTag | JSDocReadonlyTag | JSDocDeprecatedTag | JSDocOverrideTag, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { + return visitNode(cbNode, node.tagName) + || (typeof node.comment === "string" ? undefined : visitNodes(cbNode, cbNodes, node.comment)); +} + +function forEachChildInJSDocImportTag(node: JSDocImportTag, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { + return visitNode(cbNode, node.tagName) + || visitNode(cbNode, node.importClause) + || visitNode(cbNode, node.moduleSpecifier) + || visitNode(cbNode, node.attributes) + || (typeof node.comment === "string" ? undefined : visitNodes(cbNode, cbNodes, node.comment)); +} + +function forEachChildInPartiallyEmittedExpression(node: PartiallyEmittedExpression, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { + return visitNode(cbNode, node.expression); +} + +/** + * Invokes a callback for each child of the given node. The 'cbNode' callback is invoked for all child nodes + * stored in properties. If a 'cbNodes' callback is specified, it is invoked for embedded arrays; otherwise, + * embedded arrays are flattened and the 'cbNode' callback is invoked for each element. If a callback returns + * a truthy value, iteration stops and that value is returned. Otherwise, undefined is returned. + * + * @param node a given node to visit its children + * @param cbNode a callback to be invoked for all child nodes + * @param cbNodes a callback to be invoked for embedded array + * + * @remarks `forEachChild` must visit the children of a node in the order + * that they appear in the source code. The language service depends on this property to locate nodes by position. + */ +export function forEachChild(node: Node, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { + if (node === undefined || node.kind <= SyntaxKind.LastToken) { + return; + } + const fn = (forEachChildTable as Record>)[node.kind]; + return fn === undefined ? undefined : fn(node, cbNode, cbNodes); +} + +/** + * Invokes a callback for each child of the given node. The 'cbNode' callback is invoked for all child nodes + * stored in properties. If a 'cbNodes' callback is specified, it is invoked for embedded arrays; additionally, + * unlike `forEachChild`, embedded arrays are flattened and the 'cbNode' callback is invoked for each element. + * If a callback returns a truthy value, iteration stops and that value is returned. Otherwise, undefined is returned. + * + * @param node a given node to visit its children + * @param cbNode a callback to be invoked for all child nodes + * @param cbNodes a callback to be invoked for embedded array + * + * @remarks Unlike `forEachChild`, `forEachChildRecursively` handles recursively invoking the traversal on each child node found, + * and while doing so, handles traversing the structure without relying on the callstack to encode the tree structure. + * + * @internal + */ +export function forEachChildRecursively(rootNode: Node, cbNode: (node: Node, parent: Node) => T | "skip" | undefined, cbNodes?: (nodes: NodeArray, parent: Node) => T | "skip" | undefined): T | undefined { + const queue: (Node | NodeArray)[] = gatherPossibleChildren(rootNode); + const parents: Node[] = []; // tracks parent references for elements in queue + while (parents.length < queue.length) { + parents.push(rootNode); + } + while (queue.length !== 0) { + const current = queue.pop()!; + const parent = parents.pop()!; + if (isArray(current)) { + if (cbNodes) { + const res = cbNodes(current, parent); + if (res) { + if (res === "skip") continue; + return res; + } + } + for (let i = current.length - 1; i >= 0; --i) { + queue.push(current[i]); + parents.push(parent); + } + } + else { + const res = cbNode(current, parent); + if (res) { + if (res === "skip") continue; + return res; + } + if (current.kind >= SyntaxKind.FirstNode) { + // add children in reverse order to the queue, so popping gives the first child + for (const child of gatherPossibleChildren(current)) { + queue.push(child); + parents.push(current); + } + } + } + } +} + +function gatherPossibleChildren(node: Node) { + const children: (Node | NodeArray)[] = []; + forEachChild(node, addWorkItem, addWorkItem); // By using a stack above and `unshift` here, we emulate a depth-first preorder traversal + return children; + + function addWorkItem(n: Node | NodeArray) { + children.unshift(n); + } +} diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index de9ad876026..6643fd57636 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -1,55 +1,256 @@ import { - AccessorDeclaration, + AstAccessorDeclaration, + AstArrayBindingElement, + AstArrayBindingPattern, + AstArrayLiteralExpression, + AstArrayTypeNode, + AstArrowFunction, + AstAsExpression, + AstAsteriskToken, + AstBigIntLiteral, + AstBinaryExpression, + AstBinaryOperatorToken, + AstBindingElement, + AstBindingName, + AstBindingPattern, + AstBlock, + AstBooleanLiteral, + AstBreakOrContinueStatement, + AstCallSignatureDeclaration, + AstCaseBlock, + AstCaseClause, + AstCaseOrDefaultClause, + AstCatchClause, + AstClassDeclaration, + AstClassElement, + AstClassExpression, + AstClassLikeDeclaration, + AstClassStaticBlockDeclaration, + AstComputedPropertyName, + AstConciseBody, + AstConstructorDeclaration, + AstConstructSignatureDeclaration, + AstDecorator, + AstDefaultClause, + AstDoStatement, + AstDotDotDotToken, + AstEndOfFileToken, + AstEntityName, + AstEntityNameExpression, + AstEnumDeclaration, + AstEnumMember, + AstExclamationToken, + AstExportAssignment, + AstExportDeclaration, + AstExportSpecifier, + AstExpression, + AstExpressionStatement, + AstExpressionWithTypeArguments, + AstForInitializer, + AstForInOrOfStatement, + AstForStatement, + AstFunctionDeclaration, + AstFunctionExpression, + AstFunctionOrConstructorTypeNode, + AstHasJSDoc, + AstHeritageClause, + AstIdentifier, + AstIfStatement, + AstImportAttributes, + AstImportClause, + AstImportDeclaration, + AstImportEqualsDeclaration, + AstImportExpression, + AstImportSpecifier, + AstImportTypeNode, + AstIndexSignatureDeclaration, + AstInferTypeNode, + AstInterfaceDeclaration, + AstIterationStatement, + AstJSDocAllType, + AstJSDocAugmentsTag, + AstJSDocAuthorTag, + AstJSDocCallbackTag, + AstJSDocClassReference, + AstJSDocComment, + AstJSDocEnumTag, + AstJSDocFunctionType, + AstJSDocImplementsTag, + AstJSDocImportTag, + AstJSDocMemberName, + AstJSDocNameReference, + AstJSDocNamespaceDeclaration, + AstJSDocNode, + AstJSDocNullableType, + AstJSDocOptionalType, + AstJSDocOverloadTag, + AstJSDocParameterTag, + AstJSDocPropertyLikeTag, + AstJSDocPropertyTag, + AstJSDocReturnTag, + AstJSDocSatisfiesTag, + AstJSDocSeeTag, + AstJSDocSignature, + AstJSDocTag, + AstJSDocTemplateTag, + AstJSDocText, + AstJSDocThisTag, + AstJSDocThrowsTag, + AstJSDocTypedefTag, + AstJSDocTypeExpression, + AstJSDocTypeLiteral, + AstJSDocTypeTag, + AstJSDocUnknownType, + AstJsonMinusNumericLiteral, + AstJsonObjectExpressionStatement, + AstJsonSourceFile, + AstJsxAttribute, + AstJsxAttributes, + AstJsxAttributeValue, + AstJsxChild, + AstJsxClosingElement, + AstJsxClosingFragment, + AstJsxElement, + AstJsxExpression, + AstJsxFragment, + AstJsxNamespacedName, + AstJsxOpeningElement, + AstJsxOpeningFragment, + AstJsxOpeningLikeElement, + AstJsxSelfClosingElement, + AstJsxSpreadAttribute, + AstJsxTagNameExpression, + AstJsxText, + AstKeywordExpression, + AstKeywordTypeNode, + AstLabeledStatement, + AstLeftHandSideExpression, + AstLiteralExpression, + AstLiteralLikeNode, + AstLiteralTypeNode, + AstMemberExpression, + AstMetaProperty, + AstMethodDeclaration, + AstMethodSignature, + AstMinusToken, + AstMissingDeclaration, + AstModifier, + AstModifierLike, + AstModuleBlock, + AstModuleDeclaration, + AstModuleExportName, + AstNamedExportBindings, + AstNamedExports, + AstNamedImports, + AstNamespaceDeclaration, + AstNamespaceExport, + AstNamespaceExportDeclaration, + AstNamespaceImport, + AstNewExpression, + AstNode, + AstNodeArray, + AstNodeArrayLike, + AstNoSubstitutionTemplateLiteral, + AstNullLiteral, + AstNumericLiteral, + AstObjectBindingPattern, + AstObjectLiteralElementLike, + AstObjectLiteralExpression, + AstParameterDeclaration, + AstParenthesizedExpression, + AstParenthesizedTypeNode, + AstPlusToken, + AstPrefixUnaryExpression, + AstPrimaryExpression, + AstPrivateIdentifier, + AstPropertyAccessEntityNameExpression, + AstPropertyAccessExpression, + AstPropertyAssignment, + AstPropertyDeclaration, + AstPropertyName, + AstPropertySignature, + AstQualifiedName, + AstQuestionDotToken, + AstQuestionToken, + AstReadonlyKeyword, + AstReturnStatement, + AstSatisfiesExpression, + AstShorthandPropertyAssignment, + AstSourceFile, + AstStatement, + AstStringLiteral, + AstSuperExpression, + AstSwitchStatement, + AstTemplateExpression, + AstTemplateHead, + AstTemplateLiteralToken, + AstTemplateLiteralTypeNode, + AstTemplateLiteralTypeSpan, + AstTemplateMiddle, + AstTemplateSpan, + AstTemplateTail, + AstThisExpression, + AstThisTypeNode, + AstThrowStatement, + AstToken, + AstTryStatement, + AstTupleTypeNode, + AstTypeAliasDeclaration, + AstTypeAssertion, + AstTypeElement, + AstTypeLiteralNode, + AstTypeNode, + AstTypeParameterDeclaration, + AstTypePredicateNode, + AstTypeQueryNode, + AstTypeReferenceNode, + AstUnaryExpression, + AstUnionOrIntersectionTypeNode, + AstUpdateExpression, + AstVariableDeclaration, + AstVariableDeclarationList, + AstVariableStatement, + AstWhileStatement, + AstWithStatement, + AstYieldExpression, + createAstNodeFactory, + hasAstJSDocNodes, + isAstAsyncModifier, + isAstDeclareKeyword, + isAstExportModifier, + isAstExpressionWithTypeArguments, + isAstFunctionTypeNode, + isAstIdentifier, + isAstJSDocFunctionType, + isAstJSDocNullableType, + isAstJSDocReturnTag, + isAstJSDocTypeTag, + isAstJsxNamespacedName, + isAstJsxOpeningElement, + isAstJsxOpeningFragment, + isAstLeftHandSideExpression, + isAstNonNullExpression, + isAstPrivateIdentifier, + isAstSetAccessorDeclaration, + isAstStringOrNumericLiteralLike, + isAstTaggedTemplateExpression, + isAstTypeReferenceNode, +} from "./_namespaces/ts.ast.js"; +import { addRange, addRelatedInfo, append, - ArrayBindingElement, - ArrayBindingPattern, - ArrayLiteralExpression, - ArrayTypeNode, - ArrowFunction, - AsExpression, AssertionLevel, - AsteriskToken, + ast, attachFileToDiagnostics, - AwaitExpression, - BigIntLiteral, - BinaryExpression, - BinaryOperatorToken, - BindingElement, - BindingName, - BindingPattern, - Block, - BooleanLiteral, - BreakOrContinueStatement, - BreakStatement, - CallExpression, - CallSignatureDeclaration, canHaveJSDoc, canHaveModifiers, - CaseBlock, - CaseClause, - CaseOrDefaultClause, - CatchClause, CharacterCodes, - ClassDeclaration, - ClassElement, - ClassExpression, - ClassLikeDeclaration, - ClassStaticBlockDeclaration, - CommaListExpression, CommentDirective, commentPragmas, CommentRange, - ComputedPropertyName, concatenate, - ConditionalExpression, - ConditionalTypeNode, - ConstructorDeclaration, - ConstructorTypeNode, - ConstructSignatureDeclaration, containsParseError, - ContinueStatement, convertToJson, createDetachedDiagnostic, createNodeFactory, @@ -57,47 +258,21 @@ import { createTextChangeRange, createTextSpanFromBounds, Debug, - Decorator, - DefaultClause, - DeleteExpression, Diagnostic, DiagnosticArguments, DiagnosticMessage, Diagnostics, DiagnosticWithDetachedLocation, - DoStatement, - DotDotDotToken, - ElementAccessExpression, emptyArray, emptyMap, - EndOfFileToken, ensureScriptKind, EntityName, - EnumDeclaration, - EnumMember, - ExclamationToken, - ExportAssignment, - ExportDeclaration, - ExportSpecifier, - Expression, - ExpressionStatement, - ExpressionWithTypeArguments, Extension, - ExternalModuleReference, fileExtensionIs, findIndex, firstOrUndefined, forEach, - ForEachChildNodes, - ForInOrOfStatement, - ForInStatement, - ForOfStatement, - ForStatement, - FunctionDeclaration, - FunctionExpression, - FunctionOrConstructorTypeNode, - FunctionTypeNode, - GetAccessorDeclaration, + forEachChild, getAnyExtensionFromPath, getBaseFileName, getBinaryOperatorPrecedence, @@ -108,167 +283,38 @@ import { getLeadingCommentRanges, getSpellingSuggestion, getTextOfNodeFromSourceText, - HasJSDoc, - hasJSDocNodes, HasModifiers, - HeritageClause, - Identifier, identity, - idText, - IfStatement, - ImportAttribute, - ImportAttributes, - ImportClause, - ImportDeclaration, - ImportEqualsDeclaration, - ImportOrExportSpecifier, - ImportSpecifier, - ImportTypeAssertionContainer, - ImportTypeNode, - IndexedAccessTypeNode, - IndexSignatureDeclaration, - InferTypeNode, - InterfaceDeclaration, - IntersectionTypeNode, isArray, isAssignmentOperator, - isAsyncModifier, isClassMemberModifier, isExportAssignment, isExportDeclaration, - isExportModifier, - isExpressionWithTypeArguments, isExternalModuleReference, - isFunctionTypeNode, - isIdentifier as isIdentifierNode, isIdentifierText, isImportDeclaration, isImportEqualsDeclaration, - isJSDocFunctionType, - isJSDocNullableType, - isJSDocReturnTag, - isJSDocTypeTag, - isJsxNamespacedName, - isJsxOpeningElement, - isJsxOpeningFragment, isKeyword, isKeywordOrPunctuation, - isLeftHandSideExpression, isLiteralKind, isMetaProperty, isModifierKind, - isNonNullExpression, - isPrivateIdentifier, - isSetAccessorDeclaration, - isStringOrNumericLiteralLike, - isTaggedTemplateExpression, isTemplateLiteralKind, - isTypeReferenceNode, - IterationStatement, JSDoc, - JSDocAllType, - JSDocAugmentsTag, - JSDocAuthorTag, - JSDocCallbackTag, - JSDocClassTag, - JSDocComment, - JSDocDeprecatedTag, - JSDocEnumTag, - JSDocFunctionType, - JSDocImplementsTag, - JSDocImportTag, - JSDocLink, - JSDocLinkCode, - JSDocLinkPlain, - JSDocMemberName, - JSDocNameReference, - JSDocNamespaceDeclaration, - JSDocNonNullableType, - JSDocNullableType, - JSDocOptionalType, - JSDocOverloadTag, - JSDocOverrideTag, - JSDocParameterTag, JSDocParsingMode, - JSDocPrivateTag, - JSDocPropertyLikeTag, - JSDocPropertyTag, - JSDocProtectedTag, - JSDocPublicTag, - JSDocReadonlyTag, - JSDocReturnTag, - JSDocSatisfiesTag, - JSDocSeeTag, - JSDocSignature, JSDocSyntaxKind, - JSDocTag, - JSDocTemplateTag, - JSDocText, - JSDocThisTag, - JSDocThrowsTag, - JSDocTypedefTag, JSDocTypeExpression, - JSDocTypeLiteral, - JSDocTypeTag, - JSDocUnknownTag, - JSDocUnknownType, - JSDocVariadicType, - JsonMinusNumericLiteral, - JsonObjectExpressionStatement, JsonSourceFile, - JsxAttribute, - JsxAttributes, - JsxAttributeValue, - JsxChild, - JsxClosingElement, - JsxClosingFragment, - JsxElement, - JsxExpression, - JsxFragment, - JsxNamespacedName, - JsxOpeningElement, - JsxOpeningFragment, - JsxOpeningLikeElement, - JsxSelfClosingElement, - JsxSpreadAttribute, JsxTagNameExpression, - JsxText, JsxTokenSyntaxKind, - LabeledStatement, LanguageVariant, lastOrUndefined, - LeftHandSideExpression, - LiteralExpression, - LiteralLikeNode, - LiteralTypeNode, map, mapDefined, - MappedTypeNode, - MemberExpression, - MetaProperty, - MethodDeclaration, - MethodSignature, - MinusToken, - MissingDeclaration, - Modifier, ModifierFlags, - ModifierLike, modifiersToFlags, - ModuleBlock, - ModuleDeclaration, - ModuleExportName, ModuleKind, Mutable, - NamedExportBindings, - NamedExports, - NamedImports, - NamedImportsOrExports, - NamedTupleMember, - NamespaceDeclaration, - NamespaceExport, - NamespaceExportDeclaration, - NamespaceImport, - NewExpression, Node, NodeArray, NodeFactory, @@ -276,24 +322,10 @@ import { NodeFlags, nodeIsMissing, nodeIsPresent, - NonNullExpression, noop, normalizePath, - NoSubstitutionTemplateLiteral, - NullLiteral, - NumericLiteral, - ObjectBindingPattern, - ObjectLiteralElementLike, - ObjectLiteralExpression, OperatorPrecedence, - OptionalTypeNode, PackageJsonInfo, - ParameterDeclaration, - ParenthesizedExpression, - ParenthesizedTypeNode, - PartiallyEmittedExpression, - PlusToken, - PostfixUnaryExpression, PostfixUnaryOperator, PragmaContext, PragmaDefinition, @@ -301,101 +333,42 @@ import { PragmaMap, PragmaPseudoMap, PragmaPseudoMapEntry, - PrefixUnaryExpression, PrefixUnaryOperator, - PrimaryExpression, - PrivateIdentifier, - PropertyAccessEntityNameExpression, - PropertyAccessExpression, - PropertyAssignment, - PropertyDeclaration, - PropertyName, - PropertySignature, PunctuationOrKeywordSyntaxKind, PunctuationSyntaxKind, - QualifiedName, - QuestionDotToken, - QuestionToken, - ReadonlyKeyword, ReadonlyPragmaMap, ResolutionMode, - RestTypeNode, - ReturnStatement, - SatisfiesExpression, ScriptKind, ScriptTarget, - SetAccessorDeclaration, setParent, setParentRecursive, setTextRange, setTextRangePos, setTextRangePosEnd, setTextRangePosWidth, - ShorthandPropertyAssignment, skipTrivia, some, SourceFile, - SpreadAssignment, - SpreadElement, startsWith, - Statement, - StringLiteral, supportedDeclarationExtensions, - SwitchStatement, SyntaxKind, - TaggedTemplateExpression, - TemplateExpression, - TemplateHead, - TemplateLiteralToken, - TemplateLiteralTypeNode, - TemplateLiteralTypeSpan, - TemplateMiddle, - TemplateSpan, - TemplateTail, TextChangeRange, textChangeRangeIsUnchanged, textChangeRangeNewSpan, TextRange, textSpanEnd, textToKeywordObj, - ThisExpression, - ThisTypeNode, - ThrowStatement, toArray, - Token, TokenFlags, tokenIsIdentifierOrKeyword, tokenIsIdentifierOrKeywordOrGreaterThan, + TokenSyntaxKind, tokenToString, tracing, transferSourceFileChildren, TransformFlags, - TryStatement, - TupleTypeNode, - TypeAliasDeclaration, - TypeAssertion, - TypeElement, - TypeLiteralNode, - TypeNode, - TypeOfExpression, - TypeOperatorNode, - TypeParameterDeclaration, - TypePredicateNode, - TypeQueryNode, - TypeReferenceNode, - UnaryExpression, unescapeLeadingUnderscores, - UnionOrIntersectionTypeNode, - UnionTypeNode, unsetNodeChildren, - UpdateExpression, - VariableDeclaration, - VariableDeclarationList, - VariableStatement, - VoidExpression, - WhileStatement, - WithStatement, - YieldExpression, } from "./_namespaces/ts.js"; import * as performance from "./_namespaces/ts.performance.js"; @@ -417,24 +390,6 @@ const enum SpeculationKind { /** @internal */ export const parseNodeFactory: NodeFactory = createNodeFactory(NodeFactoryFlags.NoParenthesizerRules); -function visitNode(cbNode: (node: Node) => T, node: Node | undefined): T | undefined { - return node && cbNode(node); -} - -function visitNodes(cbNode: (node: Node) => T, cbNodes: ((node: NodeArray) => T | undefined) | undefined, nodes: NodeArray | undefined): T | undefined { - if (nodes) { - if (cbNodes) { - return cbNodes(nodes); - } - for (const node of nodes) { - const result = cbNode(node); - if (result) { - return result; - } - } - } -} - /** @internal */ export function isJSDocLikeText(text: string, start: number): boolean { return text.charCodeAt(start + 1) === CharacterCodes.asterisk && @@ -477,824 +432,6 @@ function isImportMeta(node: Node): boolean { return isMetaProperty(node) && node.keywordToken === SyntaxKind.ImportKeyword && node.name.escapedText === "meta"; } -type ForEachChildFunction = (node: TNode, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined) => T | undefined; -type ForEachChildTable = { [TNode in ForEachChildNodes as TNode["kind"]]: ForEachChildFunction; }; -const forEachChildTable: ForEachChildTable = { - [SyntaxKind.QualifiedName]: function forEachChildInQualifiedName(node: QualifiedName, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { - return visitNode(cbNode, node.left) || - visitNode(cbNode, node.right); - }, - [SyntaxKind.TypeParameter]: function forEachChildInTypeParameter(node: TypeParameterDeclaration, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { - return visitNodes(cbNode, cbNodes, node.modifiers) || - visitNode(cbNode, node.name) || - visitNode(cbNode, node.constraint) || - visitNode(cbNode, node.default) || - visitNode(cbNode, node.expression); - }, - [SyntaxKind.ShorthandPropertyAssignment]: function forEachChildInShorthandPropertyAssignment(node: ShorthandPropertyAssignment, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { - return visitNodes(cbNode, cbNodes, node.modifiers) || - visitNode(cbNode, node.name) || - visitNode(cbNode, node.questionToken) || - visitNode(cbNode, node.exclamationToken) || - visitNode(cbNode, node.equalsToken) || - visitNode(cbNode, node.objectAssignmentInitializer); - }, - [SyntaxKind.SpreadAssignment]: function forEachChildInSpreadAssignment(node: SpreadAssignment, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { - return visitNode(cbNode, node.expression); - }, - [SyntaxKind.Parameter]: function forEachChildInParameter(node: ParameterDeclaration, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { - return visitNodes(cbNode, cbNodes, node.modifiers) || - visitNode(cbNode, node.dotDotDotToken) || - visitNode(cbNode, node.name) || - visitNode(cbNode, node.questionToken) || - visitNode(cbNode, node.type) || - visitNode(cbNode, node.initializer); - }, - [SyntaxKind.PropertyDeclaration]: function forEachChildInPropertyDeclaration(node: PropertyDeclaration, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { - return visitNodes(cbNode, cbNodes, node.modifiers) || - visitNode(cbNode, node.name) || - visitNode(cbNode, node.questionToken) || - visitNode(cbNode, node.exclamationToken) || - visitNode(cbNode, node.type) || - visitNode(cbNode, node.initializer); - }, - [SyntaxKind.PropertySignature]: function forEachChildInPropertySignature(node: PropertySignature, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { - return visitNodes(cbNode, cbNodes, node.modifiers) || - visitNode(cbNode, node.name) || - visitNode(cbNode, node.questionToken) || - visitNode(cbNode, node.type) || - visitNode(cbNode, node.initializer); - }, - [SyntaxKind.PropertyAssignment]: function forEachChildInPropertyAssignment(node: PropertyAssignment, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { - return visitNodes(cbNode, cbNodes, node.modifiers) || - visitNode(cbNode, node.name) || - visitNode(cbNode, node.questionToken) || - visitNode(cbNode, node.exclamationToken) || - visitNode(cbNode, node.initializer); - }, - [SyntaxKind.VariableDeclaration]: function forEachChildInVariableDeclaration(node: VariableDeclaration, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { - return visitNode(cbNode, node.name) || - visitNode(cbNode, node.exclamationToken) || - visitNode(cbNode, node.type) || - visitNode(cbNode, node.initializer); - }, - [SyntaxKind.BindingElement]: function forEachChildInBindingElement(node: BindingElement, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { - return visitNode(cbNode, node.dotDotDotToken) || - visitNode(cbNode, node.propertyName) || - visitNode(cbNode, node.name) || - visitNode(cbNode, node.initializer); - }, - [SyntaxKind.IndexSignature]: function forEachChildInIndexSignature(node: IndexSignatureDeclaration, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { - return visitNodes(cbNode, cbNodes, node.modifiers) || - visitNodes(cbNode, cbNodes, node.typeParameters) || - visitNodes(cbNode, cbNodes, node.parameters) || - visitNode(cbNode, node.type); - }, - [SyntaxKind.ConstructorType]: function forEachChildInConstructorType(node: ConstructorTypeNode, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { - return visitNodes(cbNode, cbNodes, node.modifiers) || - visitNodes(cbNode, cbNodes, node.typeParameters) || - visitNodes(cbNode, cbNodes, node.parameters) || - visitNode(cbNode, node.type); - }, - [SyntaxKind.FunctionType]: function forEachChildInFunctionType(node: FunctionTypeNode, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { - return visitNodes(cbNode, cbNodes, node.modifiers) || - visitNodes(cbNode, cbNodes, node.typeParameters) || - visitNodes(cbNode, cbNodes, node.parameters) || - visitNode(cbNode, node.type); - }, - [SyntaxKind.CallSignature]: forEachChildInCallOrConstructSignature, - [SyntaxKind.ConstructSignature]: forEachChildInCallOrConstructSignature, - [SyntaxKind.MethodDeclaration]: function forEachChildInMethodDeclaration(node: MethodDeclaration, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { - return visitNodes(cbNode, cbNodes, node.modifiers) || - visitNode(cbNode, node.asteriskToken) || - visitNode(cbNode, node.name) || - visitNode(cbNode, node.questionToken) || - visitNode(cbNode, node.exclamationToken) || - visitNodes(cbNode, cbNodes, node.typeParameters) || - visitNodes(cbNode, cbNodes, node.parameters) || - visitNode(cbNode, node.type) || - visitNode(cbNode, node.body); - }, - [SyntaxKind.MethodSignature]: function forEachChildInMethodSignature(node: MethodSignature, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { - return visitNodes(cbNode, cbNodes, node.modifiers) || - visitNode(cbNode, node.name) || - visitNode(cbNode, node.questionToken) || - visitNodes(cbNode, cbNodes, node.typeParameters) || - visitNodes(cbNode, cbNodes, node.parameters) || - visitNode(cbNode, node.type); - }, - [SyntaxKind.Constructor]: function forEachChildInConstructor(node: ConstructorDeclaration, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { - return visitNodes(cbNode, cbNodes, node.modifiers) || - visitNode(cbNode, node.name) || - visitNodes(cbNode, cbNodes, node.typeParameters) || - visitNodes(cbNode, cbNodes, node.parameters) || - visitNode(cbNode, node.type) || - visitNode(cbNode, node.body); - }, - [SyntaxKind.GetAccessor]: function forEachChildInGetAccessor(node: GetAccessorDeclaration, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { - return visitNodes(cbNode, cbNodes, node.modifiers) || - visitNode(cbNode, node.name) || - visitNodes(cbNode, cbNodes, node.typeParameters) || - visitNodes(cbNode, cbNodes, node.parameters) || - visitNode(cbNode, node.type) || - visitNode(cbNode, node.body); - }, - [SyntaxKind.SetAccessor]: function forEachChildInSetAccessor(node: SetAccessorDeclaration, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { - return visitNodes(cbNode, cbNodes, node.modifiers) || - visitNode(cbNode, node.name) || - visitNodes(cbNode, cbNodes, node.typeParameters) || - visitNodes(cbNode, cbNodes, node.parameters) || - visitNode(cbNode, node.type) || - visitNode(cbNode, node.body); - }, - [SyntaxKind.FunctionDeclaration]: function forEachChildInFunctionDeclaration(node: FunctionDeclaration, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { - return visitNodes(cbNode, cbNodes, node.modifiers) || - visitNode(cbNode, node.asteriskToken) || - visitNode(cbNode, node.name) || - visitNodes(cbNode, cbNodes, node.typeParameters) || - visitNodes(cbNode, cbNodes, node.parameters) || - visitNode(cbNode, node.type) || - visitNode(cbNode, node.body); - }, - [SyntaxKind.FunctionExpression]: function forEachChildInFunctionExpression(node: FunctionExpression, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { - return visitNodes(cbNode, cbNodes, node.modifiers) || - visitNode(cbNode, node.asteriskToken) || - visitNode(cbNode, node.name) || - visitNodes(cbNode, cbNodes, node.typeParameters) || - visitNodes(cbNode, cbNodes, node.parameters) || - visitNode(cbNode, node.type) || - visitNode(cbNode, node.body); - }, - [SyntaxKind.ArrowFunction]: function forEachChildInArrowFunction(node: ArrowFunction, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { - return visitNodes(cbNode, cbNodes, node.modifiers) || - visitNodes(cbNode, cbNodes, node.typeParameters) || - visitNodes(cbNode, cbNodes, node.parameters) || - visitNode(cbNode, node.type) || - visitNode(cbNode, node.equalsGreaterThanToken) || - visitNode(cbNode, node.body); - }, - [SyntaxKind.ClassStaticBlockDeclaration]: function forEachChildInClassStaticBlockDeclaration(node: ClassStaticBlockDeclaration, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { - return visitNodes(cbNode, cbNodes, node.modifiers) || - visitNode(cbNode, node.body); - }, - [SyntaxKind.TypeReference]: function forEachChildInTypeReference(node: TypeReferenceNode, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { - return visitNode(cbNode, node.typeName) || - visitNodes(cbNode, cbNodes, node.typeArguments); - }, - [SyntaxKind.TypePredicate]: function forEachChildInTypePredicate(node: TypePredicateNode, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { - return visitNode(cbNode, node.assertsModifier) || - visitNode(cbNode, node.parameterName) || - visitNode(cbNode, node.type); - }, - [SyntaxKind.TypeQuery]: function forEachChildInTypeQuery(node: TypeQueryNode, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { - return visitNode(cbNode, node.exprName) || - visitNodes(cbNode, cbNodes, node.typeArguments); - }, - [SyntaxKind.TypeLiteral]: function forEachChildInTypeLiteral(node: TypeLiteralNode, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { - return visitNodes(cbNode, cbNodes, node.members); - }, - [SyntaxKind.ArrayType]: function forEachChildInArrayType(node: ArrayTypeNode, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { - return visitNode(cbNode, node.elementType); - }, - [SyntaxKind.TupleType]: function forEachChildInTupleType(node: TupleTypeNode, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { - return visitNodes(cbNode, cbNodes, node.elements); - }, - [SyntaxKind.UnionType]: forEachChildInUnionOrIntersectionType, - [SyntaxKind.IntersectionType]: forEachChildInUnionOrIntersectionType, - [SyntaxKind.ConditionalType]: function forEachChildInConditionalType(node: ConditionalTypeNode, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { - return visitNode(cbNode, node.checkType) || - visitNode(cbNode, node.extendsType) || - visitNode(cbNode, node.trueType) || - visitNode(cbNode, node.falseType); - }, - [SyntaxKind.InferType]: function forEachChildInInferType(node: InferTypeNode, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { - return visitNode(cbNode, node.typeParameter); - }, - [SyntaxKind.ImportType]: function forEachChildInImportType(node: ImportTypeNode, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { - return visitNode(cbNode, node.argument) || - visitNode(cbNode, node.attributes) || - visitNode(cbNode, node.qualifier) || - visitNodes(cbNode, cbNodes, node.typeArguments); - }, - [SyntaxKind.ImportTypeAssertionContainer]: function forEachChildInImportTypeAssertionContainer(node: ImportTypeAssertionContainer, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { - return visitNode(cbNode, node.assertClause); - }, - [SyntaxKind.ParenthesizedType]: forEachChildInParenthesizedTypeOrTypeOperator, - [SyntaxKind.TypeOperator]: forEachChildInParenthesizedTypeOrTypeOperator, - [SyntaxKind.IndexedAccessType]: function forEachChildInIndexedAccessType(node: IndexedAccessTypeNode, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { - return visitNode(cbNode, node.objectType) || - visitNode(cbNode, node.indexType); - }, - [SyntaxKind.MappedType]: function forEachChildInMappedType(node: MappedTypeNode, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { - return visitNode(cbNode, node.readonlyToken) || - visitNode(cbNode, node.typeParameter) || - visitNode(cbNode, node.nameType) || - visitNode(cbNode, node.questionToken) || - visitNode(cbNode, node.type) || - visitNodes(cbNode, cbNodes, node.members); - }, - [SyntaxKind.LiteralType]: function forEachChildInLiteralType(node: LiteralTypeNode, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { - return visitNode(cbNode, node.literal); - }, - [SyntaxKind.NamedTupleMember]: function forEachChildInNamedTupleMember(node: NamedTupleMember, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { - return visitNode(cbNode, node.dotDotDotToken) || - visitNode(cbNode, node.name) || - visitNode(cbNode, node.questionToken) || - visitNode(cbNode, node.type); - }, - [SyntaxKind.ObjectBindingPattern]: forEachChildInObjectOrArrayBindingPattern, - [SyntaxKind.ArrayBindingPattern]: forEachChildInObjectOrArrayBindingPattern, - [SyntaxKind.ArrayLiteralExpression]: function forEachChildInArrayLiteralExpression(node: ArrayLiteralExpression, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { - return visitNodes(cbNode, cbNodes, node.elements); - }, - [SyntaxKind.ObjectLiteralExpression]: function forEachChildInObjectLiteralExpression(node: ObjectLiteralExpression, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { - return visitNodes(cbNode, cbNodes, node.properties); - }, - [SyntaxKind.PropertyAccessExpression]: function forEachChildInPropertyAccessExpression(node: PropertyAccessExpression, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { - return visitNode(cbNode, node.expression) || - visitNode(cbNode, node.questionDotToken) || - visitNode(cbNode, node.name); - }, - [SyntaxKind.ElementAccessExpression]: function forEachChildInElementAccessExpression(node: ElementAccessExpression, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { - return visitNode(cbNode, node.expression) || - visitNode(cbNode, node.questionDotToken) || - visitNode(cbNode, node.argumentExpression); - }, - [SyntaxKind.CallExpression]: forEachChildInCallOrNewExpression, - [SyntaxKind.NewExpression]: forEachChildInCallOrNewExpression, - [SyntaxKind.TaggedTemplateExpression]: function forEachChildInTaggedTemplateExpression(node: TaggedTemplateExpression, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { - return visitNode(cbNode, node.tag) || - visitNode(cbNode, node.questionDotToken) || - visitNodes(cbNode, cbNodes, node.typeArguments) || - visitNode(cbNode, node.template); - }, - [SyntaxKind.TypeAssertionExpression]: function forEachChildInTypeAssertionExpression(node: TypeAssertion, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { - return visitNode(cbNode, node.type) || - visitNode(cbNode, node.expression); - }, - [SyntaxKind.ParenthesizedExpression]: function forEachChildInParenthesizedExpression(node: ParenthesizedExpression, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { - return visitNode(cbNode, node.expression); - }, - [SyntaxKind.DeleteExpression]: function forEachChildInDeleteExpression(node: DeleteExpression, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { - return visitNode(cbNode, node.expression); - }, - [SyntaxKind.TypeOfExpression]: function forEachChildInTypeOfExpression(node: TypeOfExpression, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { - return visitNode(cbNode, node.expression); - }, - [SyntaxKind.VoidExpression]: function forEachChildInVoidExpression(node: VoidExpression, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { - return visitNode(cbNode, node.expression); - }, - [SyntaxKind.PrefixUnaryExpression]: function forEachChildInPrefixUnaryExpression(node: PrefixUnaryExpression, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { - return visitNode(cbNode, node.operand); - }, - [SyntaxKind.YieldExpression]: function forEachChildInYieldExpression(node: YieldExpression, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { - return visitNode(cbNode, node.asteriskToken) || - visitNode(cbNode, node.expression); - }, - [SyntaxKind.AwaitExpression]: function forEachChildInAwaitExpression(node: AwaitExpression, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { - return visitNode(cbNode, node.expression); - }, - [SyntaxKind.PostfixUnaryExpression]: function forEachChildInPostfixUnaryExpression(node: PostfixUnaryExpression, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { - return visitNode(cbNode, node.operand); - }, - [SyntaxKind.BinaryExpression]: function forEachChildInBinaryExpression(node: BinaryExpression, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { - return visitNode(cbNode, node.left) || - visitNode(cbNode, node.operatorToken) || - visitNode(cbNode, node.right); - }, - [SyntaxKind.AsExpression]: function forEachChildInAsExpression(node: AsExpression, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { - return visitNode(cbNode, node.expression) || - visitNode(cbNode, node.type); - }, - [SyntaxKind.NonNullExpression]: function forEachChildInNonNullExpression(node: NonNullExpression, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { - return visitNode(cbNode, node.expression); - }, - [SyntaxKind.SatisfiesExpression]: function forEachChildInSatisfiesExpression(node: SatisfiesExpression, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { - return visitNode(cbNode, node.expression) || visitNode(cbNode, node.type); - }, - [SyntaxKind.MetaProperty]: function forEachChildInMetaProperty(node: MetaProperty, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { - return visitNode(cbNode, node.name); - }, - [SyntaxKind.ConditionalExpression]: function forEachChildInConditionalExpression(node: ConditionalExpression, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { - return visitNode(cbNode, node.condition) || - visitNode(cbNode, node.questionToken) || - visitNode(cbNode, node.whenTrue) || - visitNode(cbNode, node.colonToken) || - visitNode(cbNode, node.whenFalse); - }, - [SyntaxKind.SpreadElement]: function forEachChildInSpreadElement(node: SpreadElement, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { - return visitNode(cbNode, node.expression); - }, - [SyntaxKind.Block]: forEachChildInBlock, - [SyntaxKind.ModuleBlock]: forEachChildInBlock, - [SyntaxKind.SourceFile]: function forEachChildInSourceFile(node: SourceFile, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { - return visitNodes(cbNode, cbNodes, node.statements) || - visitNode(cbNode, node.endOfFileToken); - }, - [SyntaxKind.VariableStatement]: function forEachChildInVariableStatement(node: VariableStatement, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { - return visitNodes(cbNode, cbNodes, node.modifiers) || - visitNode(cbNode, node.declarationList); - }, - [SyntaxKind.VariableDeclarationList]: function forEachChildInVariableDeclarationList(node: VariableDeclarationList, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { - return visitNodes(cbNode, cbNodes, node.declarations); - }, - [SyntaxKind.ExpressionStatement]: function forEachChildInExpressionStatement(node: ExpressionStatement, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { - return visitNode(cbNode, node.expression); - }, - [SyntaxKind.IfStatement]: function forEachChildInIfStatement(node: IfStatement, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { - return visitNode(cbNode, node.expression) || - visitNode(cbNode, node.thenStatement) || - visitNode(cbNode, node.elseStatement); - }, - [SyntaxKind.DoStatement]: function forEachChildInDoStatement(node: DoStatement, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { - return visitNode(cbNode, node.statement) || - visitNode(cbNode, node.expression); - }, - [SyntaxKind.WhileStatement]: function forEachChildInWhileStatement(node: WhileStatement, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { - return visitNode(cbNode, node.expression) || - visitNode(cbNode, node.statement); - }, - [SyntaxKind.ForStatement]: function forEachChildInForStatement(node: ForStatement, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { - return visitNode(cbNode, node.initializer) || - visitNode(cbNode, node.condition) || - visitNode(cbNode, node.incrementor) || - visitNode(cbNode, node.statement); - }, - [SyntaxKind.ForInStatement]: function forEachChildInForInStatement(node: ForInStatement, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { - return visitNode(cbNode, node.initializer) || - visitNode(cbNode, node.expression) || - visitNode(cbNode, node.statement); - }, - [SyntaxKind.ForOfStatement]: function forEachChildInForOfStatement(node: ForOfStatement, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { - return visitNode(cbNode, node.awaitModifier) || - visitNode(cbNode, node.initializer) || - visitNode(cbNode, node.expression) || - visitNode(cbNode, node.statement); - }, - [SyntaxKind.ContinueStatement]: forEachChildInContinueOrBreakStatement, - [SyntaxKind.BreakStatement]: forEachChildInContinueOrBreakStatement, - [SyntaxKind.ReturnStatement]: function forEachChildInReturnStatement(node: ReturnStatement, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { - return visitNode(cbNode, node.expression); - }, - [SyntaxKind.WithStatement]: function forEachChildInWithStatement(node: WithStatement, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { - return visitNode(cbNode, node.expression) || - visitNode(cbNode, node.statement); - }, - [SyntaxKind.SwitchStatement]: function forEachChildInSwitchStatement(node: SwitchStatement, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { - return visitNode(cbNode, node.expression) || - visitNode(cbNode, node.caseBlock); - }, - [SyntaxKind.CaseBlock]: function forEachChildInCaseBlock(node: CaseBlock, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { - return visitNodes(cbNode, cbNodes, node.clauses); - }, - [SyntaxKind.CaseClause]: function forEachChildInCaseClause(node: CaseClause, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { - return visitNode(cbNode, node.expression) || - visitNodes(cbNode, cbNodes, node.statements); - }, - [SyntaxKind.DefaultClause]: function forEachChildInDefaultClause(node: DefaultClause, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { - return visitNodes(cbNode, cbNodes, node.statements); - }, - [SyntaxKind.LabeledStatement]: function forEachChildInLabeledStatement(node: LabeledStatement, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { - return visitNode(cbNode, node.label) || - visitNode(cbNode, node.statement); - }, - [SyntaxKind.ThrowStatement]: function forEachChildInThrowStatement(node: ThrowStatement, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { - return visitNode(cbNode, node.expression); - }, - [SyntaxKind.TryStatement]: function forEachChildInTryStatement(node: TryStatement, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { - return visitNode(cbNode, node.tryBlock) || - visitNode(cbNode, node.catchClause) || - visitNode(cbNode, node.finallyBlock); - }, - [SyntaxKind.CatchClause]: function forEachChildInCatchClause(node: CatchClause, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { - return visitNode(cbNode, node.variableDeclaration) || - visitNode(cbNode, node.block); - }, - [SyntaxKind.Decorator]: function forEachChildInDecorator(node: Decorator, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { - return visitNode(cbNode, node.expression); - }, - [SyntaxKind.ClassDeclaration]: forEachChildInClassDeclarationOrExpression, - [SyntaxKind.ClassExpression]: forEachChildInClassDeclarationOrExpression, - [SyntaxKind.InterfaceDeclaration]: function forEachChildInInterfaceDeclaration(node: InterfaceDeclaration, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { - return visitNodes(cbNode, cbNodes, node.modifiers) || - visitNode(cbNode, node.name) || - visitNodes(cbNode, cbNodes, node.typeParameters) || - visitNodes(cbNode, cbNodes, node.heritageClauses) || - visitNodes(cbNode, cbNodes, node.members); - }, - [SyntaxKind.TypeAliasDeclaration]: function forEachChildInTypeAliasDeclaration(node: TypeAliasDeclaration, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { - return visitNodes(cbNode, cbNodes, node.modifiers) || - visitNode(cbNode, node.name) || - visitNodes(cbNode, cbNodes, node.typeParameters) || - visitNode(cbNode, node.type); - }, - [SyntaxKind.EnumDeclaration]: function forEachChildInEnumDeclaration(node: EnumDeclaration, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { - return visitNodes(cbNode, cbNodes, node.modifiers) || - visitNode(cbNode, node.name) || - visitNodes(cbNode, cbNodes, node.members); - }, - [SyntaxKind.EnumMember]: function forEachChildInEnumMember(node: EnumMember, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { - return visitNode(cbNode, node.name) || - visitNode(cbNode, node.initializer); - }, - [SyntaxKind.ModuleDeclaration]: function forEachChildInModuleDeclaration(node: ModuleDeclaration, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { - return visitNodes(cbNode, cbNodes, node.modifiers) || - visitNode(cbNode, node.name) || - visitNode(cbNode, node.body); - }, - [SyntaxKind.ImportEqualsDeclaration]: function forEachChildInImportEqualsDeclaration(node: ImportEqualsDeclaration, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { - return visitNodes(cbNode, cbNodes, node.modifiers) || - visitNode(cbNode, node.name) || - visitNode(cbNode, node.moduleReference); - }, - [SyntaxKind.ImportDeclaration]: function forEachChildInImportDeclaration(node: ImportDeclaration, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { - return visitNodes(cbNode, cbNodes, node.modifiers) || - visitNode(cbNode, node.importClause) || - visitNode(cbNode, node.moduleSpecifier) || - visitNode(cbNode, node.attributes); - }, - [SyntaxKind.ImportClause]: function forEachChildInImportClause(node: ImportClause, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { - return visitNode(cbNode, node.name) || - visitNode(cbNode, node.namedBindings); - }, - [SyntaxKind.ImportAttributes]: function forEachChildInImportAttributes(node: ImportAttributes, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { - return visitNodes(cbNode, cbNodes, node.elements); - }, - [SyntaxKind.ImportAttribute]: function forEachChildInImportAttribute(node: ImportAttribute, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { - return visitNode(cbNode, node.name) || - visitNode(cbNode, node.value); - }, - [SyntaxKind.NamespaceExportDeclaration]: function forEachChildInNamespaceExportDeclaration(node: NamespaceExportDeclaration, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { - return visitNodes(cbNode, cbNodes, node.modifiers) || - visitNode(cbNode, node.name); - }, - [SyntaxKind.NamespaceImport]: function forEachChildInNamespaceImport(node: NamespaceImport, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { - return visitNode(cbNode, node.name); - }, - [SyntaxKind.NamespaceExport]: function forEachChildInNamespaceExport(node: NamespaceExport, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { - return visitNode(cbNode, node.name); - }, - [SyntaxKind.NamedImports]: forEachChildInNamedImportsOrExports, - [SyntaxKind.NamedExports]: forEachChildInNamedImportsOrExports, - [SyntaxKind.ExportDeclaration]: function forEachChildInExportDeclaration(node: ExportDeclaration, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { - return visitNodes(cbNode, cbNodes, node.modifiers) || - visitNode(cbNode, node.exportClause) || - visitNode(cbNode, node.moduleSpecifier) || - visitNode(cbNode, node.attributes); - }, - [SyntaxKind.ImportSpecifier]: forEachChildInImportOrExportSpecifier, - [SyntaxKind.ExportSpecifier]: forEachChildInImportOrExportSpecifier, - [SyntaxKind.ExportAssignment]: function forEachChildInExportAssignment(node: ExportAssignment, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { - return visitNodes(cbNode, cbNodes, node.modifiers) || - visitNode(cbNode, node.expression); - }, - [SyntaxKind.TemplateExpression]: function forEachChildInTemplateExpression(node: TemplateExpression, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { - return visitNode(cbNode, node.head) || - visitNodes(cbNode, cbNodes, node.templateSpans); - }, - [SyntaxKind.TemplateSpan]: function forEachChildInTemplateSpan(node: TemplateSpan, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { - return visitNode(cbNode, node.expression) || - visitNode(cbNode, node.literal); - }, - [SyntaxKind.TemplateLiteralType]: function forEachChildInTemplateLiteralType(node: TemplateLiteralTypeNode, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { - return visitNode(cbNode, node.head) || - visitNodes(cbNode, cbNodes, node.templateSpans); - }, - [SyntaxKind.TemplateLiteralTypeSpan]: function forEachChildInTemplateLiteralTypeSpan(node: TemplateLiteralTypeSpan, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { - return visitNode(cbNode, node.type) || - visitNode(cbNode, node.literal); - }, - [SyntaxKind.ComputedPropertyName]: function forEachChildInComputedPropertyName(node: ComputedPropertyName, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { - return visitNode(cbNode, node.expression); - }, - [SyntaxKind.HeritageClause]: function forEachChildInHeritageClause(node: HeritageClause, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { - return visitNodes(cbNode, cbNodes, node.types); - }, - [SyntaxKind.ExpressionWithTypeArguments]: function forEachChildInExpressionWithTypeArguments(node: ExpressionWithTypeArguments, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { - return visitNode(cbNode, node.expression) || - visitNodes(cbNode, cbNodes, node.typeArguments); - }, - [SyntaxKind.ExternalModuleReference]: function forEachChildInExternalModuleReference(node: ExternalModuleReference, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { - return visitNode(cbNode, node.expression); - }, - [SyntaxKind.MissingDeclaration]: function forEachChildInMissingDeclaration(node: MissingDeclaration, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { - return visitNodes(cbNode, cbNodes, node.modifiers); - }, - [SyntaxKind.CommaListExpression]: function forEachChildInCommaListExpression(node: CommaListExpression, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { - return visitNodes(cbNode, cbNodes, node.elements); - }, - [SyntaxKind.JsxElement]: function forEachChildInJsxElement(node: JsxElement, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { - return visitNode(cbNode, node.openingElement) || - visitNodes(cbNode, cbNodes, node.children) || - visitNode(cbNode, node.closingElement); - }, - [SyntaxKind.JsxFragment]: function forEachChildInJsxFragment(node: JsxFragment, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { - return visitNode(cbNode, node.openingFragment) || - visitNodes(cbNode, cbNodes, node.children) || - visitNode(cbNode, node.closingFragment); - }, - [SyntaxKind.JsxSelfClosingElement]: forEachChildInJsxOpeningOrSelfClosingElement, - [SyntaxKind.JsxOpeningElement]: forEachChildInJsxOpeningOrSelfClosingElement, - [SyntaxKind.JsxAttributes]: function forEachChildInJsxAttributes(node: JsxAttributes, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { - return visitNodes(cbNode, cbNodes, node.properties); - }, - [SyntaxKind.JsxAttribute]: function forEachChildInJsxAttribute(node: JsxAttribute, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { - return visitNode(cbNode, node.name) || - visitNode(cbNode, node.initializer); - }, - [SyntaxKind.JsxSpreadAttribute]: function forEachChildInJsxSpreadAttribute(node: JsxSpreadAttribute, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { - return visitNode(cbNode, node.expression); - }, - [SyntaxKind.JsxExpression]: function forEachChildInJsxExpression(node: JsxExpression, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { - return visitNode(cbNode, node.dotDotDotToken) || - visitNode(cbNode, node.expression); - }, - [SyntaxKind.JsxClosingElement]: function forEachChildInJsxClosingElement(node: JsxClosingElement, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { - return visitNode(cbNode, node.tagName); - }, - [SyntaxKind.JsxNamespacedName]: function forEachChildInJsxNamespacedName(node: JsxNamespacedName, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { - return visitNode(cbNode, node.namespace) || - visitNode(cbNode, node.name); - }, - [SyntaxKind.OptionalType]: forEachChildInOptionalRestOrJSDocParameterModifier, - [SyntaxKind.RestType]: forEachChildInOptionalRestOrJSDocParameterModifier, - [SyntaxKind.JSDocTypeExpression]: forEachChildInOptionalRestOrJSDocParameterModifier, - [SyntaxKind.JSDocNonNullableType]: forEachChildInOptionalRestOrJSDocParameterModifier, - [SyntaxKind.JSDocNullableType]: forEachChildInOptionalRestOrJSDocParameterModifier, - [SyntaxKind.JSDocOptionalType]: forEachChildInOptionalRestOrJSDocParameterModifier, - [SyntaxKind.JSDocVariadicType]: forEachChildInOptionalRestOrJSDocParameterModifier, - [SyntaxKind.JSDocFunctionType]: function forEachChildInJSDocFunctionType(node: JSDocFunctionType, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { - return visitNodes(cbNode, cbNodes, node.parameters) || - visitNode(cbNode, node.type); - }, - [SyntaxKind.JSDoc]: function forEachChildInJSDoc(node: JSDoc, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { - return (typeof node.comment === "string" ? undefined : visitNodes(cbNode, cbNodes, node.comment)) - || visitNodes(cbNode, cbNodes, node.tags); - }, - [SyntaxKind.JSDocSeeTag]: function forEachChildInJSDocSeeTag(node: JSDocSeeTag, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { - return visitNode(cbNode, node.tagName) || - visitNode(cbNode, node.name) || - (typeof node.comment === "string" ? undefined : visitNodes(cbNode, cbNodes, node.comment)); - }, - [SyntaxKind.JSDocNameReference]: function forEachChildInJSDocNameReference(node: JSDocNameReference, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { - return visitNode(cbNode, node.name); - }, - [SyntaxKind.JSDocMemberName]: function forEachChildInJSDocMemberName(node: JSDocMemberName, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { - return visitNode(cbNode, node.left) || - visitNode(cbNode, node.right); - }, - [SyntaxKind.JSDocParameterTag]: forEachChildInJSDocParameterOrPropertyTag, - [SyntaxKind.JSDocPropertyTag]: forEachChildInJSDocParameterOrPropertyTag, - [SyntaxKind.JSDocAuthorTag]: function forEachChildInJSDocAuthorTag(node: JSDocAuthorTag, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { - return visitNode(cbNode, node.tagName) || - (typeof node.comment === "string" ? undefined : visitNodes(cbNode, cbNodes, node.comment)); - }, - [SyntaxKind.JSDocImplementsTag]: function forEachChildInJSDocImplementsTag(node: JSDocImplementsTag, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { - return visitNode(cbNode, node.tagName) || - visitNode(cbNode, node.class) || - (typeof node.comment === "string" ? undefined : visitNodes(cbNode, cbNodes, node.comment)); - }, - [SyntaxKind.JSDocAugmentsTag]: function forEachChildInJSDocAugmentsTag(node: JSDocAugmentsTag, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { - return visitNode(cbNode, node.tagName) || - visitNode(cbNode, node.class) || - (typeof node.comment === "string" ? undefined : visitNodes(cbNode, cbNodes, node.comment)); - }, - [SyntaxKind.JSDocTemplateTag]: function forEachChildInJSDocTemplateTag(node: JSDocTemplateTag, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { - return visitNode(cbNode, node.tagName) || - visitNode(cbNode, node.constraint) || - visitNodes(cbNode, cbNodes, node.typeParameters) || - (typeof node.comment === "string" ? undefined : visitNodes(cbNode, cbNodes, node.comment)); - }, - [SyntaxKind.JSDocTypedefTag]: function forEachChildInJSDocTypedefTag(node: JSDocTypedefTag, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { - return visitNode(cbNode, node.tagName) || - (node.typeExpression && - node.typeExpression.kind === SyntaxKind.JSDocTypeExpression - ? visitNode(cbNode, node.typeExpression) || - visitNode(cbNode, node.fullName) || - (typeof node.comment === "string" ? undefined : visitNodes(cbNode, cbNodes, node.comment)) - : visitNode(cbNode, node.fullName) || - visitNode(cbNode, node.typeExpression) || - (typeof node.comment === "string" ? undefined : visitNodes(cbNode, cbNodes, node.comment))); - }, - [SyntaxKind.JSDocCallbackTag]: function forEachChildInJSDocCallbackTag(node: JSDocCallbackTag, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { - return visitNode(cbNode, node.tagName) || - visitNode(cbNode, node.fullName) || - visitNode(cbNode, node.typeExpression) || - (typeof node.comment === "string" ? undefined : visitNodes(cbNode, cbNodes, node.comment)); - }, - [SyntaxKind.JSDocReturnTag]: forEachChildInJSDocTypeLikeTag, - [SyntaxKind.JSDocTypeTag]: forEachChildInJSDocTypeLikeTag, - [SyntaxKind.JSDocThisTag]: forEachChildInJSDocTypeLikeTag, - [SyntaxKind.JSDocEnumTag]: forEachChildInJSDocTypeLikeTag, - [SyntaxKind.JSDocSatisfiesTag]: forEachChildInJSDocTypeLikeTag, - [SyntaxKind.JSDocThrowsTag]: forEachChildInJSDocTypeLikeTag, - [SyntaxKind.JSDocOverloadTag]: forEachChildInJSDocTypeLikeTag, - [SyntaxKind.JSDocSignature]: function forEachChildInJSDocSignature(node: JSDocSignature, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { - return forEach(node.typeParameters, cbNode) || - forEach(node.parameters, cbNode) || - visitNode(cbNode, node.type); - }, - [SyntaxKind.JSDocLink]: forEachChildInJSDocLinkCodeOrPlain, - [SyntaxKind.JSDocLinkCode]: forEachChildInJSDocLinkCodeOrPlain, - [SyntaxKind.JSDocLinkPlain]: forEachChildInJSDocLinkCodeOrPlain, - [SyntaxKind.JSDocTypeLiteral]: function forEachChildInJSDocTypeLiteral(node: JSDocTypeLiteral, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { - return forEach(node.jsDocPropertyTags, cbNode); - }, - [SyntaxKind.JSDocTag]: forEachChildInJSDocTag, - [SyntaxKind.JSDocClassTag]: forEachChildInJSDocTag, - [SyntaxKind.JSDocPublicTag]: forEachChildInJSDocTag, - [SyntaxKind.JSDocPrivateTag]: forEachChildInJSDocTag, - [SyntaxKind.JSDocProtectedTag]: forEachChildInJSDocTag, - [SyntaxKind.JSDocReadonlyTag]: forEachChildInJSDocTag, - [SyntaxKind.JSDocDeprecatedTag]: forEachChildInJSDocTag, - [SyntaxKind.JSDocOverrideTag]: forEachChildInJSDocTag, - [SyntaxKind.JSDocImportTag]: forEachChildInJSDocImportTag, - [SyntaxKind.PartiallyEmittedExpression]: forEachChildInPartiallyEmittedExpression, -}; - -// shared - -function forEachChildInCallOrConstructSignature(node: CallSignatureDeclaration | ConstructSignatureDeclaration, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { - return visitNodes(cbNode, cbNodes, node.typeParameters) || - visitNodes(cbNode, cbNodes, node.parameters) || - visitNode(cbNode, node.type); -} - -function forEachChildInUnionOrIntersectionType(node: UnionTypeNode | IntersectionTypeNode, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { - return visitNodes(cbNode, cbNodes, node.types); -} - -function forEachChildInParenthesizedTypeOrTypeOperator(node: ParenthesizedTypeNode | TypeOperatorNode, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { - return visitNode(cbNode, node.type); -} - -function forEachChildInObjectOrArrayBindingPattern(node: BindingPattern, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { - return visitNodes(cbNode, cbNodes, node.elements); -} - -function forEachChildInCallOrNewExpression(node: CallExpression | NewExpression, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { - return visitNode(cbNode, node.expression) || - // TODO: should we separate these branches out? - visitNode(cbNode, (node as CallExpression).questionDotToken) || - visitNodes(cbNode, cbNodes, node.typeArguments) || - visitNodes(cbNode, cbNodes, node.arguments); -} - -function forEachChildInBlock(node: Block | ModuleBlock, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { - return visitNodes(cbNode, cbNodes, node.statements); -} - -function forEachChildInContinueOrBreakStatement(node: ContinueStatement | BreakStatement, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { - return visitNode(cbNode, node.label); -} - -function forEachChildInClassDeclarationOrExpression(node: ClassDeclaration | ClassExpression, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { - return visitNodes(cbNode, cbNodes, node.modifiers) || - visitNode(cbNode, node.name) || - visitNodes(cbNode, cbNodes, node.typeParameters) || - visitNodes(cbNode, cbNodes, node.heritageClauses) || - visitNodes(cbNode, cbNodes, node.members); -} - -function forEachChildInNamedImportsOrExports(node: NamedImports | NamedExports, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { - return visitNodes(cbNode, cbNodes, node.elements); -} - -function forEachChildInImportOrExportSpecifier(node: ImportSpecifier | ExportSpecifier, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { - return visitNode(cbNode, node.propertyName) || - visitNode(cbNode, node.name); -} - -function forEachChildInJsxOpeningOrSelfClosingElement(node: JsxOpeningLikeElement, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { - return visitNode(cbNode, node.tagName) || - visitNodes(cbNode, cbNodes, node.typeArguments) || - visitNode(cbNode, node.attributes); -} - -function forEachChildInOptionalRestOrJSDocParameterModifier(node: OptionalTypeNode | RestTypeNode | JSDocTypeExpression | JSDocNullableType | JSDocNonNullableType | JSDocOptionalType | JSDocVariadicType, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { - return visitNode(cbNode, node.type); -} - -function forEachChildInJSDocParameterOrPropertyTag(node: JSDocParameterTag | JSDocPropertyTag, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { - return visitNode(cbNode, node.tagName) || - (node.isNameFirst - ? visitNode(cbNode, node.name) || visitNode(cbNode, node.typeExpression) - : visitNode(cbNode, node.typeExpression) || visitNode(cbNode, node.name)) || - (typeof node.comment === "string" ? undefined : visitNodes(cbNode, cbNodes, node.comment)); -} - -function forEachChildInJSDocTypeLikeTag(node: JSDocReturnTag | JSDocTypeTag | JSDocThisTag | JSDocEnumTag | JSDocThrowsTag | JSDocOverloadTag | JSDocSatisfiesTag, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { - return visitNode(cbNode, node.tagName) || - visitNode(cbNode, node.typeExpression) || - (typeof node.comment === "string" ? undefined : visitNodes(cbNode, cbNodes, node.comment)); -} - -function forEachChildInJSDocLinkCodeOrPlain(node: JSDocLink | JSDocLinkCode | JSDocLinkPlain, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { - return visitNode(cbNode, node.name); -} - -function forEachChildInJSDocTag(node: JSDocUnknownTag | JSDocClassTag | JSDocPublicTag | JSDocPrivateTag | JSDocProtectedTag | JSDocReadonlyTag | JSDocDeprecatedTag | JSDocOverrideTag, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { - return visitNode(cbNode, node.tagName) - || (typeof node.comment === "string" ? undefined : visitNodes(cbNode, cbNodes, node.comment)); -} - -function forEachChildInJSDocImportTag(node: JSDocImportTag, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { - return visitNode(cbNode, node.tagName) - || visitNode(cbNode, node.importClause) - || visitNode(cbNode, node.moduleSpecifier) - || visitNode(cbNode, node.attributes) - || (typeof node.comment === "string" ? undefined : visitNodes(cbNode, cbNodes, node.comment)); -} - -function forEachChildInPartiallyEmittedExpression(node: PartiallyEmittedExpression, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { - return visitNode(cbNode, node.expression); -} - -/** - * Invokes a callback for each child of the given node. The 'cbNode' callback is invoked for all child nodes - * stored in properties. If a 'cbNodes' callback is specified, it is invoked for embedded arrays; otherwise, - * embedded arrays are flattened and the 'cbNode' callback is invoked for each element. If a callback returns - * a truthy value, iteration stops and that value is returned. Otherwise, undefined is returned. - * - * @param node a given node to visit its children - * @param cbNode a callback to be invoked for all child nodes - * @param cbNodes a callback to be invoked for embedded array - * - * @remarks `forEachChild` must visit the children of a node in the order - * that they appear in the source code. The language service depends on this property to locate nodes by position. - */ -export function forEachChild(node: Node, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray) => T | undefined): T | undefined { - if (node === undefined || node.kind <= SyntaxKind.LastToken) { - return; - } - const fn = (forEachChildTable as Record>)[node.kind]; - return fn === undefined ? undefined : fn(node, cbNode, cbNodes); -} - -/** - * Invokes a callback for each child of the given node. The 'cbNode' callback is invoked for all child nodes - * stored in properties. If a 'cbNodes' callback is specified, it is invoked for embedded arrays; additionally, - * unlike `forEachChild`, embedded arrays are flattened and the 'cbNode' callback is invoked for each element. - * If a callback returns a truthy value, iteration stops and that value is returned. Otherwise, undefined is returned. - * - * @param node a given node to visit its children - * @param cbNode a callback to be invoked for all child nodes - * @param cbNodes a callback to be invoked for embedded array - * - * @remarks Unlike `forEachChild`, `forEachChildRecursively` handles recursively invoking the traversal on each child node found, - * and while doing so, handles traversing the structure without relying on the callstack to encode the tree structure. - * - * @internal - */ -export function forEachChildRecursively(rootNode: Node, cbNode: (node: Node, parent: Node) => T | "skip" | undefined, cbNodes?: (nodes: NodeArray, parent: Node) => T | "skip" | undefined): T | undefined { - const queue: (Node | NodeArray)[] = gatherPossibleChildren(rootNode); - const parents: Node[] = []; // tracks parent references for elements in queue - while (parents.length < queue.length) { - parents.push(rootNode); - } - while (queue.length !== 0) { - const current = queue.pop()!; - const parent = parents.pop()!; - if (isArray(current)) { - if (cbNodes) { - const res = cbNodes(current, parent); - if (res) { - if (res === "skip") continue; - return res; - } - } - for (let i = current.length - 1; i >= 0; --i) { - queue.push(current[i]); - parents.push(parent); - } - } - else { - const res = cbNode(current, parent); - if (res) { - if (res === "skip") continue; - return res; - } - if (current.kind >= SyntaxKind.FirstNode) { - // add children in reverse order to the queue, so popping gives the first child - for (const child of gatherPossibleChildren(current)) { - queue.push(child); - parents.push(current); - } - } - } - } -} - -function gatherPossibleChildren(node: Node) { - const children: (Node | NodeArray)[] = []; - forEachChild(node, addWorkItem, addWorkItem); // By using a stack above and `unshift` here, we emulate a depth-first preorder traversal - return children; - - function addWorkItem(n: Node | NodeArray) { - children.unshift(n); - } -} - export interface CreateSourceFileOptions { languageVersion: ScriptTarget; /** @@ -1321,7 +458,7 @@ function setExternalModuleIndicator(sourceFile: SourceFile) { export function createSourceFile(fileName: string, sourceText: string, languageVersionOrOptions: ScriptTarget | CreateSourceFileOptions, setParentNodes = false, scriptKind?: ScriptKind): SourceFile { tracing?.push(tracing.Phase.Parse, "createSourceFile", { path: fileName }, /*separateBeginAndEnd*/ true); performance.mark("beforeParse"); - let result: SourceFile; + let result: AstSourceFile; const { languageVersion, @@ -1343,7 +480,7 @@ export function createSourceFile(fileName: string, sourceText: string, languageV performance.mark("afterParse"); performance.measure("Parse", "beforeParse", "afterParse"); tracing?.pop(); - return result; + return result.node; } export function parseIsolatedEntityName(text: string, languageVersion: ScriptTarget): EntityName | undefined { @@ -1356,7 +493,7 @@ export function parseIsolatedEntityName(text: string, languageVersion: ScriptTar * @param sourceText */ export function parseJsonText(fileName: string, sourceText: string): JsonSourceFile { - return Parser.parseJsonText(fileName, sourceText); + return Parser.parseJsonText(fileName, sourceText).node; } // See also `isExternalOrCommonJsModule` in utilities.ts @@ -1374,11 +511,11 @@ export function isExternalModule(file: SourceFile): boolean { // becoming detached from any SourceFile). It is recommended that this SourceFile not // be used once 'update' is called on it. export function updateSourceFile(sourceFile: SourceFile, newText: string, textChangeRange: TextChangeRange, aggressiveChecks = false): SourceFile { - const newSourceFile = IncrementalParser.updateSourceFile(sourceFile, newText, textChangeRange, aggressiveChecks); + const newSourceFile = IncrementalParser.updateSourceFile((sourceFile as AstSourceFile["node"]).ast, newText, textChangeRange, aggressiveChecks); // Because new source file node is created, it may not have the flag PossiblyContainDynamicImport. This is the case if there is no new edit to add dynamic import. // We will manually port the flag to the new source file. - (newSourceFile as Mutable).flags |= sourceFile.flags & NodeFlags.PermanentlySetIncrementalFlags; - return newSourceFile; + newSourceFile.flags |= sourceFile.flags & NodeFlags.PermanentlySetIncrementalFlags; + return newSourceFile.node; } /** @internal */ @@ -1393,7 +530,7 @@ export function parseIsolatedJSDocComment(content: string, start?: number, lengt if (result && result.jsDoc) { // because the jsDocComment was parsed out of the source file, it might // not be covered by the fixupParentReferences. - Parser.fixupParentReferences(result.jsDoc); + Parser.fixupParentReferences((result.jsDoc as AstJSDocNode["node"]).ast); } return result; @@ -1422,7 +559,7 @@ namespace Parser { var disallowInAndDecoratorContext = NodeFlags.DisallowInContext | NodeFlags.DecoratorContext; - var factory = createNodeFactory(NodeFactoryFlags.NoParenthesizerRules | NodeFactoryFlags.NoNodeConverters | NodeFactoryFlags.NoOriginalNode, _ => { + var factory = createAstNodeFactory(NodeFactoryFlags.NoParenthesizerRules | NodeFactoryFlags.NoNodeConverters | NodeFactoryFlags.NoOriginalNode, _ => { nodeCount++; }); @@ -1556,7 +693,7 @@ namespace Parser { // attached to the EOF token. var parseErrorBeforeNextFinishedNode = false; - var missingLists: Set>; + var missingLists: Set>; /* eslint-enable no-var */ export function parseSourceFile( @@ -1568,17 +705,17 @@ namespace Parser { scriptKind?: ScriptKind, setExternalModuleIndicatorOverride?: (file: SourceFile) => void, jsDocParsingMode = JSDocParsingMode.ParseAll, - ): SourceFile { + ): AstSourceFile { scriptKind = ensureScriptKind(fileName, scriptKind); if (scriptKind === ScriptKind.JSON) { const result = parseJsonText(fileName, sourceText, languageVersion, syntaxCursor, setParentNodes); - convertToJson(result, result.statements[0]?.expression, result.parseDiagnostics, /*returnValue*/ false, /*jsonConversionNotifier*/ undefined); - result.referencedFiles = emptyArray; - result.typeReferenceDirectives = emptyArray; - result.libReferenceDirectives = emptyArray; - result.amdDependencies = emptyArray; - result.hasNoDefaultLib = false; - result.pragmas = emptyMap as ReadonlyPragmaMap; + convertToJson(result.node, result.data.statements.items[0]?.data.expression.node, result.data.parseDiagnostics, /*returnValue*/ false, /*jsonConversionNotifier*/ undefined); + result.data.referencedFiles = emptyArray; + result.data.typeReferenceDirectives = emptyArray; + result.data.libReferenceDirectives = emptyArray; + result.data.amdDependencies = emptyArray; + result.data.hasNoDefaultLib = false; + result.data.pragmas = emptyMap as ReadonlyPragmaMap; return result; } @@ -1599,10 +736,10 @@ namespace Parser { const entityName = parseEntityName(/*allowReservedWords*/ true); const isValid = token() === SyntaxKind.EndOfFileToken && !parseDiagnostics.length; clearState(); - return isValid ? entityName : undefined; + return isValid ? entityName.node : undefined; } - export function parseJsonText(fileName: string, sourceText: string, languageVersion: ScriptTarget = ScriptTarget.ES2015, syntaxCursor?: IncrementalParser.SyntaxCursor, setParentNodes = false): JsonSourceFile { + export function parseJsonText(fileName: string, sourceText: string, languageVersion: ScriptTarget = ScriptTarget.ES2015, syntaxCursor?: IncrementalParser.SyntaxCursor, setParentNodes = false): AstJsonSourceFile { initializeState(fileName, sourceText, languageVersion, syntaxCursor, ScriptKind.JSON, JSDocParsingMode.ParseAll); sourceFlags = contextFlags; @@ -1611,13 +748,13 @@ namespace Parser { const pos = getNodePos(); let statements, endOfFileToken; if (token() === SyntaxKind.EndOfFileToken) { - statements = createNodeArray([], pos, pos); - endOfFileToken = parseTokenNode(); + statements = createNodeArray([], pos, pos); + endOfFileToken = parseTokenNode(); } else { // Loop and synthesize an ArrayLiteralExpression if there are more than // one top-level expressions to ensure all input text is consumed. - let expressions: Expression[] | Expression | undefined; + let expressions: AstExpression[] | AstExpression | undefined; while (token() !== SyntaxKind.EndOfFileToken) { let expression; switch (token()) { @@ -1627,11 +764,11 @@ namespace Parser { case SyntaxKind.TrueKeyword: case SyntaxKind.FalseKeyword: case SyntaxKind.NullKeyword: - expression = parseTokenNode(); + expression = parseTokenNode(); break; case SyntaxKind.MinusToken: if (lookAhead(() => nextToken() === SyntaxKind.NumericLiteral && nextToken() !== SyntaxKind.ColonToken)) { - expression = parsePrefixUnaryExpression() as JsonMinusNumericLiteral; + expression = parsePrefixUnaryExpression() as AstJsonMinusNumericLiteral; } else { expression = parseObjectLiteralExpression(); @@ -1640,7 +777,7 @@ namespace Parser { case SyntaxKind.NumericLiteral: case SyntaxKind.StringLiteral: if (lookAhead(() => nextToken() !== SyntaxKind.ColonToken)) { - expression = parseLiteralNode() as StringLiteral | NumericLiteral; + expression = parseLiteralNode() as AstStringLiteral | AstNumericLiteral; break; } // falls through @@ -1665,10 +802,10 @@ namespace Parser { } const expression = isArray(expressions) ? finishNode(factoryCreateArrayLiteralExpression(expressions), pos) : Debug.checkDefined(expressions); - const statement = factoryCreateExpressionStatement(expression) as JsonObjectExpressionStatement; + const statement = factoryCreateExpressionStatement(expression) as AstJsonObjectExpressionStatement; finishNode(statement, pos); statements = createNodeArray([statement], pos); - endOfFileToken = parseExpectedToken(SyntaxKind.EndOfFileToken, Diagnostics.Unexpected_token) as EndOfFileToken; + endOfFileToken = parseExpectedToken(SyntaxKind.EndOfFileToken, Diagnostics.Unexpected_token) as AstEndOfFileToken; } // Set source file so that errors will be reported with this file name @@ -1678,15 +815,15 @@ namespace Parser { fixupParentReferences(sourceFile); } - sourceFile.nodeCount = nodeCount; - sourceFile.identifierCount = identifierCount; - sourceFile.identifiers = identifiers; - sourceFile.parseDiagnostics = attachFileToDiagnostics(parseDiagnostics, sourceFile); + sourceFile.data.nodeCount = nodeCount; + sourceFile.data.identifierCount = identifierCount; + sourceFile.data.identifiers = identifiers; + sourceFile.data.parseDiagnostics = attachFileToDiagnostics(parseDiagnostics, sourceFile.node); // TODO(rbuckton): do not instantiate node if (jsDocDiagnostics) { - sourceFile.jsDocDiagnostics = attachFileToDiagnostics(jsDocDiagnostics, sourceFile); + sourceFile.data.jsDocDiagnostics = attachFileToDiagnostics(jsDocDiagnostics, sourceFile.node); // TODO(rbuckton): do not instantiate node } - const result = sourceFile as JsonSourceFile; + const result = sourceFile as AstJsonSourceFile; clearState(); return result; } @@ -1755,7 +892,7 @@ namespace Parser { topLevel = true; } - function parseSourceFileWorker(languageVersion: ScriptTarget, setParentNodes: boolean, scriptKind: ScriptKind, setExternalModuleIndicator: (file: SourceFile) => void, jsDocParsingMode: JSDocParsingMode): SourceFile { + function parseSourceFileWorker(languageVersion: ScriptTarget, setParentNodes: boolean, scriptKind: ScriptKind, setExternalModuleIndicator: (file: SourceFile) => void, jsDocParsingMode: JSDocParsingMode): AstSourceFile { const isDeclarationFile = isDeclarationFileName(fileName); if (isDeclarationFile) { contextFlags |= NodeFlags.Ambient; @@ -1769,22 +906,22 @@ namespace Parser { const statements = parseList(ParsingContext.SourceElements, parseStatement); Debug.assert(token() === SyntaxKind.EndOfFileToken); const endHasJSDoc = hasPrecedingJSDocComment(); - const endOfFileToken = withJSDoc(parseTokenNode(), endHasJSDoc); + const endOfFileToken = withJSDoc(parseTokenNode(), endHasJSDoc); const sourceFile = createSourceFile(fileName, languageVersion, scriptKind, isDeclarationFile, statements, endOfFileToken, sourceFlags, setExternalModuleIndicator); // A member of ReadonlyArray isn't assignable to a member of T[] (and prevents a direct cast) - but this is where we set up those members so they can be readonly in the future - processCommentPragmas(sourceFile as {} as PragmaContext, sourceText); - processPragmasIntoFields(sourceFile as {} as PragmaContext, reportPragmaDiagnostic); + processCommentPragmas(sourceFile.data as {} as PragmaContext, sourceText); + processPragmasIntoFields(sourceFile.data as {} as PragmaContext, reportPragmaDiagnostic); - sourceFile.commentDirectives = scanner.getCommentDirectives(); - sourceFile.nodeCount = nodeCount; - sourceFile.identifierCount = identifierCount; - sourceFile.identifiers = identifiers; - sourceFile.parseDiagnostics = attachFileToDiagnostics(parseDiagnostics, sourceFile); - sourceFile.jsDocParsingMode = jsDocParsingMode; + sourceFile.data.commentDirectives = scanner.getCommentDirectives(); + sourceFile.data.nodeCount = nodeCount; + sourceFile.data.identifierCount = identifierCount; + sourceFile.data.identifiers = identifiers; + sourceFile.data.parseDiagnostics = attachFileToDiagnostics(parseDiagnostics, sourceFile.node); // TODO(rbuckton): do not instantiate node + sourceFile.data.jsDocParsingMode = jsDocParsingMode; if (jsDocDiagnostics) { - sourceFile.jsDocDiagnostics = attachFileToDiagnostics(jsDocDiagnostics, sourceFile); + sourceFile.data.jsDocDiagnostics = attachFileToDiagnostics(jsDocDiagnostics, sourceFile.node); // TODO(rbuckton): do not instantiate node } if (setParentNodes) { @@ -1799,14 +936,14 @@ namespace Parser { } let hasDeprecatedTag = false; - function withJSDoc(node: T, hasJSDoc: boolean): T { + function withJSDoc(node: T, hasJSDoc: boolean): T { if (!hasJSDoc) { return node; } - Debug.assert(!node.jsDoc); // Should only be called once per node - const jsDoc = mapDefined(getJSDocCommentRanges(node, sourceText), comment => JSDocParser.parseJSDocComment(node, comment.pos, comment.end - comment.pos)); - if (jsDoc.length) node.jsDoc = jsDoc; + Debug.assert(!node.data.jsDoc); // Should only be called once per node + const jsDoc = mapDefined(getJSDocCommentRanges(node, sourceText), comment => JSDocParser.parseJSDocComment(node, comment.pos, comment.end - comment.pos)?.node); // TODO(rbuckton): do not instantiate .node + if (jsDoc.length) node.data.jsDoc = jsDoc; if (hasDeprecatedTag) { hasDeprecatedTag = false; (node as Mutable).flags |= NodeFlags.Deprecated; @@ -1814,24 +951,24 @@ namespace Parser { return node; } - function reparseTopLevelAwait(sourceFile: SourceFile) { + function reparseTopLevelAwait(sourceFile: AstSourceFile) { const savedSyntaxCursor = syntaxCursor; const baseSyntaxCursor = IncrementalParser.createSyntaxCursor(sourceFile); syntaxCursor = { currentNode }; - const statements: Statement[] = []; + const statements: AstStatement[] = []; const savedParseDiagnostics = parseDiagnostics; parseDiagnostics = []; let pos = 0; - let start = findNextStatementWithAwait(sourceFile.statements, 0); + let start = findNextStatementWithAwait(sourceFile.data.statements, 0); while (start !== -1) { // append all statements between pos and start - const prevStatement = sourceFile.statements[pos]; - const nextStatement = sourceFile.statements[start]; - addRange(statements, sourceFile.statements, pos, start); - pos = findNextStatementWithoutAwait(sourceFile.statements, start); + const prevStatement = sourceFile.data.statements.items[pos]; + const nextStatement = sourceFile.data.statements.items[start]; + addRange(statements, sourceFile.data.statements.items, pos, start); + pos = findNextStatementWithoutAwait(sourceFile.data.statements, start); // append all diagnostics associated with the copied range const diagnosticStart = findIndex(savedParseDiagnostics, diagnostic => diagnostic.start >= prevStatement.pos); @@ -1856,14 +993,14 @@ namespace Parser { } if (pos >= 0) { - const nonAwaitStatement = sourceFile.statements[pos]; + const nonAwaitStatement = sourceFile.data.statements.items[pos]; if (statement.end === nonAwaitStatement.pos) { // done reparsing this section break; } if (statement.end > nonAwaitStatement.pos) { // we ate into the next statement, so we must reparse it. - pos = findNextStatementWithoutAwait(sourceFile.statements, pos + 1); + pos = findNextStatementWithoutAwait(sourceFile.data.statements, pos + 1); } } } @@ -1872,13 +1009,13 @@ namespace Parser { }, SpeculationKind.Reparse); // find the next statement containing an `await` - start = pos >= 0 ? findNextStatementWithAwait(sourceFile.statements, pos) : -1; + start = pos >= 0 ? findNextStatementWithAwait(sourceFile.data.statements, pos) : -1; } // append all statements between pos and the end of the list if (pos >= 0) { - const prevStatement = sourceFile.statements[pos]; - addRange(statements, sourceFile.statements, pos); + const prevStatement = sourceFile.data.statements.items[pos]; + addRange(statements, sourceFile.data.statements.items, pos); // append all diagnostics associated with the copied range const diagnosticStart = findIndex(savedParseDiagnostics, diagnostic => diagnostic.start >= prevStatement.pos); @@ -1888,25 +1025,25 @@ namespace Parser { } syntaxCursor = savedSyntaxCursor; - return factory.updateSourceFile(sourceFile, setTextRange(factoryCreateNodeArray(statements), sourceFile.statements)); + return factory.updateSourceFile(sourceFile, setTextRange(factoryCreateNodeArray(statements), sourceFile.data.statements)); - function containsPossibleTopLevelAwait(node: Node) { + function containsPossibleTopLevelAwait(node: AstNode) { return !(node.flags & NodeFlags.AwaitContext) && !!(node.transformFlags & TransformFlags.ContainsPossibleTopLevelAwait); } - function findNextStatementWithAwait(statements: NodeArray, start: number) { - for (let i = start; i < statements.length; i++) { - if (containsPossibleTopLevelAwait(statements[i])) { + function findNextStatementWithAwait(statements: AstNodeArray, start: number) { + for (let i = start; i < statements.items.length; i++) { + if (containsPossibleTopLevelAwait(statements.items[i])) { return i; } } return -1; } - function findNextStatementWithoutAwait(statements: NodeArray, start: number) { - for (let i = start; i < statements.length; i++) { - if (!containsPossibleTopLevelAwait(statements[i])) { + function findNextStatementWithoutAwait(statements: AstNodeArray, start: number) { + for (let i = start; i < statements.items.length; i++) { + if (!containsPossibleTopLevelAwait(statements.items[i])) { return i; } } @@ -1922,12 +1059,12 @@ namespace Parser { } } - export function fixupParentReferences(rootNode: Node) { + export function fixupParentReferences(rootNode: AstNode) { // normally parent references are set during binding. However, for clients that only need // a syntax tree, and no semantic features, then the binding process is an unnecessary // overhead. This functions allows us to set all the parents, without all the expense of // binding. - setParentRecursive(rootNode, /*incremental*/ true); + setParentRecursive(rootNode.node, /*incremental*/ true); // TODO: do not instantiate node } function createSourceFile( @@ -1935,11 +1072,11 @@ namespace Parser { languageVersion: ScriptTarget, scriptKind: ScriptKind, isDeclarationFile: boolean, - statements: readonly Statement[], - endOfFileToken: EndOfFileToken, + statements: AstNodeArrayLike, + endOfFileToken: AstEndOfFileToken, flags: NodeFlags, setExternalModuleIndicator: (sourceFile: SourceFile) => void, - ): SourceFile { + ): AstSourceFile { // code from createNode is inlined here so createNode won't have to deal with special case of creating source files // this is quite rare comparing to other nodes and createNode should be as fast as possible let sourceFile = factory.createSourceFile(statements, endOfFileToken, flags); @@ -1947,7 +1084,7 @@ namespace Parser { setFields(sourceFile); // If we parsed this as an external module, it may contain top-level await - if (!isDeclarationFile && isExternalModule(sourceFile) && sourceFile.transformFlags & TransformFlags.ContainsPossibleTopLevelAwait) { + if (!isDeclarationFile && isExternalModule(sourceFile.node) && sourceFile.transformFlags & TransformFlags.ContainsPossibleTopLevelAwait) { const oldSourceFile = sourceFile; sourceFile = reparseTopLevelAwait(sourceFile); if (oldSourceFile !== sourceFile) setFields(sourceFile); @@ -1955,18 +1092,18 @@ namespace Parser { return sourceFile; - function setFields(sourceFile: SourceFile) { - sourceFile.text = sourceText; - sourceFile.bindDiagnostics = []; - sourceFile.bindSuggestionDiagnostics = undefined; - sourceFile.languageVersion = languageVersion; - sourceFile.fileName = fileName; - sourceFile.languageVariant = getLanguageVariant(scriptKind); - sourceFile.isDeclarationFile = isDeclarationFile; - sourceFile.scriptKind = scriptKind; + function setFields(sourceFile: AstSourceFile) { + sourceFile.data.text = sourceText; + sourceFile.data.bindDiagnostics = []; + sourceFile.data.bindSuggestionDiagnostics = undefined; + sourceFile.data.languageVersion = languageVersion; + sourceFile.data.fileName = fileName; + sourceFile.data.languageVariant = getLanguageVariant(scriptKind); + sourceFile.data.isDeclarationFile = isDeclarationFile; + sourceFile.data.scriptKind = scriptKind; - setExternalModuleIndicator(sourceFile); - sourceFile.setExternalModuleIndicator = setExternalModuleIndicator; + setExternalModuleIndicator(sourceFile.node); + sourceFile.data.setExternalModuleIndicator = setExternalModuleIndicator; } } @@ -2316,17 +1453,17 @@ namespace Parser { * * @param node Node preceding the expected semicolon location. */ - function parseErrorForMissingSemicolonAfter(node: Expression | PropertyName): void { + function parseErrorForMissingSemicolonAfter(node: AstExpression | AstPropertyName): void { // 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 (isTaggedTemplateExpression(node)) { - parseErrorAt(skipTrivia(sourceText, node.template.pos), node.template.end, Diagnostics.Module_declaration_names_may_only_use_or_quoted_strings); + if (isAstTaggedTemplateExpression(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 = isIdentifierNode(node) ? idText(node) : undefined; + const expressionText = isAstIdentifier(node) ? unescapeLeadingUnderscores(node.data.escapedText) : undefined; if (!expressionText || !isIdentifierText(expressionText, languageVersion)) { parseErrorAtCurrentToken(Diagnostics._0_expected, tokenToString(SyntaxKind.SemicolonToken)); return; @@ -2406,7 +1543,7 @@ namespace Parser { return undefined; } - function parseSemicolonAfterPropertyName(name: PropertyName, type: TypeNode | undefined, initializer: Expression | undefined) { + function parseSemicolonAfterPropertyName(name: AstPropertyName, type: AstTypeNode | undefined, initializer: AstExpression | undefined) { if (token() === SyntaxKind.AtToken && !scanner.hasPrecedingLineBreak()) { parseErrorAtCurrentToken(Diagnostics.Decorators_must_precede_the_name_and_all_keywords_of_property_declarations); return; @@ -2475,48 +1612,50 @@ namespace Parser { return false; } - function parseOptionalToken(t: TKind): Token; - function parseOptionalToken(t: SyntaxKind): Node | undefined { + function parseOptionalToken(t: TKind): AstToken; + function parseOptionalToken(t: TokenSyntaxKind): AstNode | undefined { if (token() === t) { return parseTokenNode(); } return undefined; } - function parseOptionalTokenJSDoc(t: TKind): Token; - function parseOptionalTokenJSDoc(t: JSDocSyntaxKind): Node | undefined { + function parseOptionalTokenJSDoc(t: TKind): AstToken; + function parseOptionalTokenJSDoc(t: JSDocSyntaxKind): AstNode | undefined { if (token() === t) { return parseTokenNodeJSDoc(); } return undefined; } - function parseExpectedToken(t: TKind, diagnosticMessage?: DiagnosticMessage, arg0?: string): Token; - function parseExpectedToken(t: SyntaxKind, diagnosticMessage?: DiagnosticMessage, arg0?: string): Node { + function parseExpectedToken(t: TKind, diagnosticMessage?: DiagnosticMessage, arg0?: string): AstToken; + function parseExpectedToken(t: TokenSyntaxKind, diagnosticMessage?: DiagnosticMessage, arg0?: string): AstToken { return parseOptionalToken(t) || createMissingNode(t, /*reportAtCurrentPosition*/ false, diagnosticMessage || Diagnostics._0_expected, arg0 || tokenToString(t)!); } - function parseExpectedTokenJSDoc(t: TKind): Token; - function parseExpectedTokenJSDoc(t: JSDocSyntaxKind): Node { + function parseExpectedTokenJSDoc(t: TKind): AstToken; + function parseExpectedTokenJSDoc(t: JSDocSyntaxKind): AstNode { const optional = parseOptionalTokenJSDoc(t); if (optional) return optional; Debug.assert(isKeywordOrPunctuation(t)); return createMissingNode(t, /*reportAtCurrentPosition*/ false, Diagnostics._0_expected, tokenToString(t)); } - function parseTokenNode(): T { + function parseTokenNode(): T { const pos = getNodePos(); const kind = token(); nextToken(); - return finishNode(factoryCreateToken(kind), pos) as T; + // TODO(rbuckton): verify assertion + return finishNode(factoryCreateToken(kind as TokenSyntaxKind), pos) as T; } - function parseTokenNodeJSDoc(): T { + function parseTokenNodeJSDoc(): T { const pos = getNodePos(); const kind = token(); nextTokenJSDoc(); - return finishNode(factoryCreateToken(kind), pos) as T; + // TODO(rbuckton): verify assertion + return finishNode(factoryCreateToken(kind as TokenSyntaxKind), pos) as T; } function canParseSemicolon() { @@ -2546,13 +1685,13 @@ namespace Parser { return tryParseSemicolon() || parseExpected(SyntaxKind.SemicolonToken); } - function createNodeArray(elements: T[], pos: number, end?: number, hasTrailingComma?: boolean): NodeArray { + function createNodeArray(elements: T[], pos: number, end?: number, hasTrailingComma?: boolean): AstNodeArray { const array = factoryCreateNodeArray(elements, hasTrailingComma); setTextRangePosEnd(array, pos, end ?? scanner.getTokenFullStart()); return array; } - function finishNode(node: T, pos: number, end?: number): T { + function finishNode(node: T, pos: number, end?: number): T { setTextRangePosEnd(node, pos, end ?? scanner.getTokenFullStart()); if (contextFlags) { (node as Mutable).flags |= contextFlags; @@ -2569,9 +1708,9 @@ namespace Parser { return node; } - function createMissingNode(kind: T["kind"], reportAtCurrentPosition: false, diagnosticMessage?: DiagnosticMessage, ...args: DiagnosticArguments): T; - function createMissingNode(kind: T["kind"], reportAtCurrentPosition: boolean, diagnosticMessage: DiagnosticMessage, ...args: DiagnosticArguments): T; - function createMissingNode(kind: T["kind"], reportAtCurrentPosition: boolean, diagnosticMessage?: DiagnosticMessage, ...args: DiagnosticArguments): T { + function createMissingNode(kind: T["kind"], reportAtCurrentPosition: false, diagnosticMessage?: DiagnosticMessage, ...args: DiagnosticArguments): T; + function createMissingNode(kind: T["kind"], reportAtCurrentPosition: boolean, diagnosticMessage: DiagnosticMessage, ...args: DiagnosticArguments): T; + function createMissingNode(kind: T["kind"], reportAtCurrentPosition: boolean, diagnosticMessage?: DiagnosticMessage, ...args: DiagnosticArguments): T { if (reportAtCurrentPosition) { parseErrorAtPosition(scanner.getTokenFullStart(), 0, diagnosticMessage!, ...args); } @@ -2580,12 +1719,12 @@ namespace Parser { } const pos = getNodePos(); - const result = kind === SyntaxKind.Identifier ? factoryCreateIdentifier("", /*originalKeywordKind*/ undefined) : + const result = kind === SyntaxKind.Identifier ? factoryCreateIdentifier("") : isTemplateLiteralKind(kind) ? factory.createTemplateLiteralLikeNode(kind, "", "", /*templateFlags*/ undefined) : kind === SyntaxKind.NumericLiteral ? factoryCreateNumericLiteral("", /*numericLiteralFlags*/ undefined) : kind === SyntaxKind.StringLiteral ? factoryCreateStringLiteral("", /*isSingleQuote*/ undefined) : kind === SyntaxKind.MissingDeclaration ? factory.createMissingDeclaration() : - factoryCreateToken(kind); + factoryCreateToken(kind as TokenSyntaxKind); // TODO(rbuckton): verify assertion return finishNode(result, pos) as T; } @@ -2600,16 +1739,14 @@ namespace Parser { // An identifier that starts with two underscores has an extra underscore character prepended to it to avoid issues // with magic property names like '__proto__'. The 'identifiers' object is used to share a single string instance for // each identifier in order to reduce memory consumption. - function createIdentifier(isIdentifier: boolean, diagnosticMessage?: DiagnosticMessage, privateIdentifierDiagnosticMessage?: DiagnosticMessage): Identifier { + function createIdentifier(isIdentifier: boolean, diagnosticMessage?: DiagnosticMessage, privateIdentifierDiagnosticMessage?: DiagnosticMessage): AstIdentifier { if (isIdentifier) { identifierCount++; const pos = scanner.hasPrecedingJSDocLeadingAsterisks() ? scanner.getTokenStart() : getNodePos(); - // Store original token kind if it is not just an Identifier so we can report appropriate error later in type checker - const originalKeywordKind = token(); const text = internIdentifier(scanner.getTokenValue()); const hasExtendedUnicodeEscape = scanner.hasExtendedUnicodeEscape(); nextTokenWithoutCheck(); - return finishNode(factoryCreateIdentifier(text, originalKeywordKind, hasExtendedUnicodeEscape), pos); + return finishNode(factoryCreateIdentifier(text, hasExtendedUnicodeEscape), pos); } if (token() === SyntaxKind.PrivateIdentifier) { @@ -2633,22 +1770,22 @@ namespace Parser { Diagnostics.Identifier_expected_0_is_a_reserved_word_that_cannot_be_used_here : Diagnostics.Identifier_expected; - return createMissingNode(SyntaxKind.Identifier, reportAtCurrentPosition, diagnosticMessage || defaultMessage, msgArg); + return createMissingNode(SyntaxKind.Identifier, reportAtCurrentPosition, diagnosticMessage || defaultMessage, msgArg); } function parseBindingIdentifier(privateIdentifierDiagnosticMessage?: DiagnosticMessage) { return createIdentifier(isBindingIdentifier(), /*diagnosticMessage*/ undefined, privateIdentifierDiagnosticMessage); } - function parseIdentifier(diagnosticMessage?: DiagnosticMessage, privateIdentifierDiagnosticMessage?: DiagnosticMessage): Identifier { + function parseIdentifier(diagnosticMessage?: DiagnosticMessage, privateIdentifierDiagnosticMessage?: DiagnosticMessage): AstIdentifier { return createIdentifier(isIdentifier(), diagnosticMessage, privateIdentifierDiagnosticMessage); } - function parseIdentifierName(diagnosticMessage?: DiagnosticMessage): Identifier { + function parseIdentifierName(diagnosticMessage?: DiagnosticMessage): AstIdentifier { return createIdentifier(tokenIsIdentifierOrKeyword(token()), diagnosticMessage); } - function parseIdentifierNameErrorOnUnicodeEscapeSequence(): Identifier { + function parseIdentifierNameErrorOnUnicodeEscapeSequence(): AstIdentifier { if (scanner.hasUnicodeEscape() || scanner.hasExtendedUnicodeEscape()) { parseErrorAtCurrentToken(Diagnostics.Unicode_escape_sequence_cannot_appear_here); } @@ -2666,10 +1803,10 @@ namespace Parser { return tokenIsIdentifierOrKeyword(token()) || token() === SyntaxKind.StringLiteral; } - function parsePropertyNameWorker(allowComputedPropertyNames: boolean): PropertyName { + function parsePropertyNameWorker(allowComputedPropertyNames: boolean): AstPropertyName { if (token() === SyntaxKind.StringLiteral || token() === SyntaxKind.NumericLiteral || token() === SyntaxKind.BigIntLiteral) { - const node = parseLiteralNode() as StringLiteral | NumericLiteral | BigIntLiteral; - node.text = internIdentifier(node.text); + const node = parseLiteralNode() as AstStringLiteral | AstNumericLiteral | AstBigIntLiteral; + node.data.text = internIdentifier(node.data.text); return node; } if (allowComputedPropertyNames && token() === SyntaxKind.OpenBracketToken) { @@ -2681,11 +1818,11 @@ namespace Parser { return parseIdentifierName(); } - function parsePropertyName(): PropertyName { + function parsePropertyName(): AstPropertyName { return parsePropertyNameWorker(/*allowComputedPropertyNames*/ true); } - function parseComputedPropertyName(): ComputedPropertyName { + function parseComputedPropertyName(): AstComputedPropertyName { // PropertyName [Yield]: // LiteralPropertyName // ComputedPropertyName[?Yield] @@ -2699,7 +1836,7 @@ namespace Parser { return finishNode(factory.createComputedPropertyName(expression), pos); } - function parsePrivateIdentifier(): PrivateIdentifier { + function parsePrivateIdentifier(): AstPrivateIdentifier { const pos = getNodePos(); const node = factoryCreatePrivateIdentifier(internIdentifier(scanner.getTokenValue())); nextToken(); @@ -3039,7 +2176,7 @@ namespace Parser { } // Parses a list of elements - function parseList(kind: ParsingContext, parseElement: () => T): NodeArray { + function parseList(kind: ParsingContext, parseElement: () => T): AstNodeArray { const saveParsingContext = parsingContext; parsingContext |= 1 << kind; const list = []; @@ -3061,7 +2198,7 @@ namespace Parser { return createNodeArray(list, listPos); } - function parseListElement(parsingContext: ParsingContext, parseElement: () => T): T { + function parseListElement(parsingContext: ParsingContext, parseElement: () => T): T { const node = currentNode(parsingContext); if (node) { return consumeNode(node) as T; @@ -3070,7 +2207,7 @@ namespace Parser { return parseElement(); } - function currentNode(parsingContext: ParsingContext, pos?: number): Node | undefined { + function currentNode(parsingContext: ParsingContext, pos?: number): AstNode | undefined { // If we don't have a cursor or the parsing context isn't reusable, there's nothing to reuse. // // If there is an outstanding parse error that we've encountered, but not attached to @@ -3116,15 +2253,15 @@ namespace Parser { return undefined; } - if (canHaveJSDoc(node) && node.jsDoc?.jsDocCache) { + if (canHaveJSDoc(node) && node.data.jsDoc?.jsDocCache) { // jsDocCache may include tags from parent nodes, which might have been modified. - node.jsDoc.jsDocCache = undefined; + node.data.jsDoc.jsDocCache = undefined; } return node; } - function consumeNode(node: Node) { + function consumeNode(node: AstNode) { // Move the scanner so it is after the node we just consumed. scanner.resetTokenState(node.end); nextToken(); @@ -3148,7 +2285,7 @@ namespace Parser { return false; } - function canReuseNode(node: Node, parsingContext: ParsingContext): boolean { + function canReuseNode(node: AstNode, parsingContext: ParsingContext): boolean { switch (parsingContext) { case ParsingContext.ClassMembers: return isReusableClassMember(node); @@ -3226,7 +2363,7 @@ namespace Parser { return false; } - function isReusableClassMember(node: Node) { + function isReusableClassMember(node: AstNode) { if (node) { switch (node.kind) { case SyntaxKind.Constructor: @@ -3240,9 +2377,9 @@ namespace Parser { // Method declarations are not necessarily reusable. An object-literal // may have a method calls "constructor(...)" and we must reparse that // into an actual .ConstructorDeclaration. - const methodDeclaration = node as MethodDeclaration; - const nameIsConstructor = methodDeclaration.name.kind === SyntaxKind.Identifier && - methodDeclaration.name.escapedText === "constructor"; + const methodDeclaration = node as AstMethodDeclaration; + const nameIsConstructor = methodDeclaration.data.name.kind === SyntaxKind.Identifier && + methodDeclaration.data.name.data.escapedText === "constructor"; return !nameIsConstructor; } @@ -3251,7 +2388,7 @@ namespace Parser { return false; } - function isReusableSwitchClause(node: Node) { + function isReusableSwitchClause(node: AstNode) { if (node) { switch (node.kind) { case SyntaxKind.CaseClause: @@ -3263,7 +2400,7 @@ namespace Parser { return false; } - function isReusableStatement(node: Node) { + function isReusableStatement(node: AstNode) { if (node) { switch (node.kind) { case SyntaxKind.FunctionDeclaration: @@ -3302,11 +2439,11 @@ namespace Parser { return false; } - function isReusableEnumMember(node: Node) { + function isReusableEnumMember(node: AstNode) { return node.kind === SyntaxKind.EnumMember; } - function isReusableTypeMember(node: Node) { + function isReusableTypeMember(node: AstNode) { if (node) { switch (node.kind) { case SyntaxKind.ConstructSignature: @@ -3321,7 +2458,7 @@ namespace Parser { return false; } - function isReusableVariableDeclaration(node: Node) { + function isReusableVariableDeclaration(node: AstNode) { if (node.kind !== SyntaxKind.VariableDeclaration) { return false; } @@ -3340,18 +2477,18 @@ namespace Parser { // // In order to prevent this, we do not allow a variable declarator to be reused if it // has an initializer. - const variableDeclarator = node as VariableDeclaration; - return variableDeclarator.initializer === undefined; + const variableDeclarator = node as AstVariableDeclaration; + return variableDeclarator.data.initializer === undefined; } - function isReusableParameter(node: Node) { + function isReusableParameter(node: AstNode) { if (node.kind !== SyntaxKind.Parameter) { return false; } // See the comment in isReusableVariableDeclaration for why we do this. - const parameter = node as ParameterDeclaration; - return parameter.initializer === undefined; + const parameter = node as AstParameterDeclaration; + return parameter.data.initializer === undefined; } // Returns true if we should abort parsing. @@ -3435,9 +2572,9 @@ namespace Parser { } // Parses a comma-delimited list of elements - function parseDelimitedList(kind: ParsingContext, parseElement: () => T, considerSemicolonAsDelimiter?: boolean): NodeArray; - function parseDelimitedList(kind: ParsingContext, parseElement: () => T, considerSemicolonAsDelimiter?: boolean): NodeArray> | undefined; - function parseDelimitedList(kind: ParsingContext, parseElement: () => T, considerSemicolonAsDelimiter?: boolean): NodeArray> | undefined { + function parseDelimitedList(kind: ParsingContext, parseElement: () => T, considerSemicolonAsDelimiter?: boolean): AstNodeArray; + function parseDelimitedList(kind: ParsingContext, parseElement: () => T, considerSemicolonAsDelimiter?: boolean): AstNodeArray> | undefined; + function parseDelimitedList(kind: ParsingContext, parseElement: () => T, considerSemicolonAsDelimiter?: boolean): AstNodeArray> | undefined { const saveParsingContext = parsingContext; parsingContext |= 1 << kind; const list: NonNullable[] = []; @@ -3510,17 +2647,17 @@ namespace Parser { return kind === ParsingContext.EnumMembers ? Diagnostics.An_enum_member_name_must_be_followed_by_a_or : undefined; } - function createMissingList(): NodeArray { + function createMissingList(): AstNodeArray { const list = createNodeArray([], getNodePos()); missingLists.add(list); return list; } - function isMissingList(arr: NodeArray): boolean { + function isMissingList(arr: AstNodeArray): boolean { return missingLists.has(arr); } - function parseBracketedList(kind: ParsingContext, parseElement: () => T, open: PunctuationSyntaxKind, close: PunctuationSyntaxKind): NodeArray { + function parseBracketedList(kind: ParsingContext, parseElement: () => T, open: PunctuationSyntaxKind, close: PunctuationSyntaxKind): AstNodeArray { if (parseExpected(open)) { const result = parseDelimitedList(kind, parseElement); parseExpected(close); @@ -3530,9 +2667,9 @@ namespace Parser { return createMissingList(); } - function parseEntityName(allowReservedWords: boolean, diagnosticMessage?: DiagnosticMessage): EntityName { + function parseEntityName(allowReservedWords: boolean, diagnosticMessage?: DiagnosticMessage): AstEntityName { const pos = getNodePos(); - let entity: EntityName = allowReservedWords ? parseIdentifierName(diagnosticMessage) : parseIdentifier(diagnosticMessage); + let entity: AstEntityName = allowReservedWords ? parseIdentifierName(diagnosticMessage) : parseIdentifier(diagnosticMessage); while (parseOptional(SyntaxKind.DotToken)) { if (token() === SyntaxKind.LessThanToken) { // The entity is part of a JSDoc-style generic. We will use the gap between `typeName` and @@ -3542,7 +2679,7 @@ namespace Parser { entity = finishNode( factory.createQualifiedName( entity, - parseRightSideOfDot(allowReservedWords, /*allowPrivateIdentifiers*/ false, /*allowUnicodeEscapeSequenceInIdentifierName*/ true) as Identifier, + parseRightSideOfDot(allowReservedWords, /*allowPrivateIdentifiers*/ false, /*allowUnicodeEscapeSequenceInIdentifierName*/ true) as AstIdentifier, ), pos, ); @@ -3550,11 +2687,11 @@ namespace Parser { return entity; } - function createQualifiedName(entity: EntityName, name: Identifier): QualifiedName { + function createQualifiedName(entity: AstEntityName, name: AstIdentifier): AstQualifiedName { return finishNode(factory.createQualifiedName(entity, name), entity.pos); } - function parseRightSideOfDot(allowIdentifierNames: boolean, allowPrivateIdentifiers: boolean, allowUnicodeEscapeSequenceInIdentifierName: boolean): Identifier | PrivateIdentifier { + function parseRightSideOfDot(allowIdentifierNames: boolean, allowPrivateIdentifiers: boolean, allowUnicodeEscapeSequenceInIdentifierName: boolean): AstIdentifier | AstPrivateIdentifier { // Technically a keyword is valid here as all identifiers and keywords are identifier names. // However, often we'll encounter this in error situations when the identifier or keyword // is actually starting another valid construct. @@ -3581,13 +2718,13 @@ namespace Parser { // Report that we need an identifier. However, report it right after the dot, // and not on the next token. This is because the next token might actually // be an identifier and the error would be quite confusing. - return createMissingNode(SyntaxKind.Identifier, /*reportAtCurrentPosition*/ true, Diagnostics.Identifier_expected); + return createMissingNode(SyntaxKind.Identifier, /*reportAtCurrentPosition*/ true, Diagnostics.Identifier_expected); } } if (token() === SyntaxKind.PrivateIdentifier) { const node = parsePrivateIdentifier(); - return allowPrivateIdentifiers ? node : createMissingNode(SyntaxKind.Identifier, /*reportAtCurrentPosition*/ true, Diagnostics.Identifier_expected); + return allowPrivateIdentifiers ? node : createMissingNode(SyntaxKind.Identifier, /*reportAtCurrentPosition*/ true, Diagnostics.Identifier_expected); } if (allowIdentifierNames) { @@ -3600,16 +2737,16 @@ namespace Parser { function parseTemplateSpans(isTaggedTemplate: boolean) { const pos = getNodePos(); const list = []; - let node: TemplateSpan; + let node: AstTemplateSpan; do { node = parseTemplateSpan(isTaggedTemplate); list.push(node); } - while (node.literal.kind === SyntaxKind.TemplateMiddle); + while (node.data.literal.kind === SyntaxKind.TemplateMiddle); return createNodeArray(list, pos); } - function parseTemplateExpression(isTaggedTemplate: boolean): TemplateExpression { + function parseTemplateExpression(isTaggedTemplate: boolean): AstTemplateExpression { const pos = getNodePos(); return finishNode( factory.createTemplateExpression( @@ -3620,7 +2757,7 @@ namespace Parser { ); } - function parseTemplateType(): TemplateLiteralTypeNode { + function parseTemplateType(): AstTemplateLiteralTypeNode { const pos = getNodePos(); return finishNode( factory.createTemplateLiteralType( @@ -3634,16 +2771,16 @@ namespace Parser { function parseTemplateTypeSpans() { const pos = getNodePos(); const list = []; - let node: TemplateLiteralTypeSpan; + let node: AstTemplateLiteralTypeSpan; do { node = parseTemplateTypeSpan(); list.push(node); } - while (node.literal.kind === SyntaxKind.TemplateMiddle); + while (node.data.literal.kind === SyntaxKind.TemplateMiddle); return createNodeArray(list, pos); } - function parseTemplateTypeSpan(): TemplateLiteralTypeSpan { + function parseTemplateTypeSpan(): AstTemplateLiteralTypeSpan { const pos = getNodePos(); return finishNode( factory.createTemplateLiteralTypeSpan( @@ -3654,18 +2791,18 @@ namespace Parser { ); } - function parseLiteralOfTemplateSpan(isTaggedTemplate: boolean) { + function parseLiteralOfTemplateSpan(isTaggedTemplate: boolean): AstTemplateMiddle | AstTemplateTail { if (token() === SyntaxKind.CloseBraceToken) { reScanTemplateToken(isTaggedTemplate); return parseTemplateMiddleOrTemplateTail(); } else { // TODO(rbuckton): Do we need to call `parseExpectedToken` or can we just call `createMissingNode` directly? - return parseExpectedToken(SyntaxKind.TemplateTail, Diagnostics._0_expected, tokenToString(SyntaxKind.CloseBraceToken)) as TemplateTail; + return parseExpectedToken(SyntaxKind.TemplateTail, Diagnostics._0_expected, tokenToString(SyntaxKind.CloseBraceToken)) as AstTemplateTail; } } - function parseTemplateSpan(isTaggedTemplate: boolean): TemplateSpan { + function parseTemplateSpan(isTaggedTemplate: boolean): AstTemplateSpan { const pos = getNodePos(); return finishNode( factory.createTemplateSpan( @@ -3676,32 +2813,32 @@ namespace Parser { ); } - function parseLiteralNode(): LiteralExpression { - return parseLiteralLikeNode(token()) as LiteralExpression; + function parseLiteralNode(): AstLiteralExpression { + return parseLiteralLikeNode(token()) as AstLiteralExpression; } - function parseTemplateHead(isTaggedTemplate: boolean): TemplateHead { + function parseTemplateHead(isTaggedTemplate: boolean): AstTemplateHead { if (!isTaggedTemplate && scanner.getTokenFlags() & TokenFlags.IsInvalid) { reScanTemplateToken(/*isTaggedTemplate*/ false); } const fragment = parseLiteralLikeNode(token()); Debug.assert(fragment.kind === SyntaxKind.TemplateHead, "Template head has wrong token kind"); - return fragment as TemplateHead; + return fragment as AstTemplateHead; } - function parseTemplateMiddleOrTemplateTail(): TemplateMiddle | TemplateTail { + function parseTemplateMiddleOrTemplateTail(): AstTemplateMiddle | AstTemplateTail { const fragment = parseLiteralLikeNode(token()); Debug.assert(fragment.kind === SyntaxKind.TemplateMiddle || fragment.kind === SyntaxKind.TemplateTail, "Template fragment has wrong token kind"); - return fragment as TemplateMiddle | TemplateTail; + return fragment as AstTemplateMiddle | AstTemplateTail; } - function getTemplateLiteralRawText(kind: TemplateLiteralToken["kind"]) { + function getTemplateLiteralRawText(kind: AstTemplateLiteralToken["kind"]) { const isLast = kind === SyntaxKind.NoSubstitutionTemplateLiteral || kind === SyntaxKind.TemplateTail; const tokenText = scanner.getTokenText(); return tokenText.substring(1, tokenText.length - (scanner.isUnterminated() ? 0 : isLast ? 1 : 2)); } - function parseLiteralLikeNode(kind: SyntaxKind): LiteralLikeNode { + function parseLiteralLikeNode(kind: SyntaxKind): AstLiteralLikeNode { const pos = getNodePos(); const node = isTemplateLiteralKind(kind) ? factory.createTemplateLiteralLikeNode(kind, scanner.getTokenValue(), getTemplateLiteralRawText(kind), scanner.getTokenFlags() & TokenFlags.TemplateLiteralLikeFlags) : // Note that theoretically the following condition would hold true literals like 009, @@ -3714,12 +2851,21 @@ namespace Parser { isLiteralKind(kind) ? factoryCreateLiteralLikeNode(kind, scanner.getTokenValue()) : Debug.fail(); - if (scanner.hasExtendedUnicodeEscape()) { - node.hasExtendedUnicodeEscape = true; - } - - if (scanner.isUnterminated()) { - node.isUnterminated = true; + switch (node.kind) { + case SyntaxKind.TemplateHead: + case SyntaxKind.TemplateMiddle: + case SyntaxKind.TemplateTail: + case SyntaxKind.NoSubstitutionTemplateLiteral: + case SyntaxKind.StringLiteral: + case SyntaxKind.JsxText: + case SyntaxKind.RegularExpressionLiteral: + if (scanner.hasExtendedUnicodeEscape()) { + node.data.hasExtendedUnicodeEscape = true; + } + if (scanner.isUnterminated()) { + node.data.isUnterminated = true; + } + break; } nextToken(); @@ -3738,7 +2884,7 @@ namespace Parser { } } - function parseTypeReference(): TypeReferenceNode { + function parseTypeReference(): AstTypeReferenceNode { const pos = getNodePos(); return finishNode( factory.createTypeReferenceNode( @@ -3750,46 +2896,46 @@ namespace Parser { } // If true, we should abort parsing an error function. - function typeHasArrowFunctionBlockingParseError(node: TypeNode): boolean { + function typeHasArrowFunctionBlockingParseError(node: AstTypeNode): boolean { switch (node.kind) { case SyntaxKind.TypeReference: - return nodeIsMissing((node as TypeReferenceNode).typeName); + return nodeIsMissing((node as AstTypeReferenceNode).data.typeName); case SyntaxKind.FunctionType: case SyntaxKind.ConstructorType: { - const { parameters, type } = node as FunctionOrConstructorTypeNode; + const { data: { parameters, type } } = node as AstFunctionOrConstructorTypeNode; return isMissingList(parameters) || typeHasArrowFunctionBlockingParseError(type); } case SyntaxKind.ParenthesizedType: - return typeHasArrowFunctionBlockingParseError((node as ParenthesizedTypeNode).type); + return typeHasArrowFunctionBlockingParseError((node as AstParenthesizedTypeNode).data.type); default: return false; } } - function parseThisTypePredicate(lhs: ThisTypeNode): TypePredicateNode { + function parseThisTypePredicate(lhs: AstThisTypeNode): AstTypePredicateNode { nextToken(); return finishNode(factory.createTypePredicateNode(/*assertsModifier*/ undefined, lhs, parseType()), lhs.pos); } - function parseThisTypeNode(): ThisTypeNode { + function parseThisTypeNode(): AstThisTypeNode { const pos = getNodePos(); nextToken(); return finishNode(factory.createThisTypeNode(), pos); } - function parseJSDocAllType(): JSDocAllType | JSDocOptionalType { + function parseJSDocAllType(): AstJSDocAllType | AstJSDocOptionalType { const pos = getNodePos(); nextToken(); return finishNode(factory.createJSDocAllType(), pos); } - function parseJSDocNonNullableType(): TypeNode { + function parseJSDocNonNullableType(): AstTypeNode { const pos = getNodePos(); nextToken(); return finishNode(factory.createJSDocNonNullableType(parseNonArrayType(), /*postfix*/ false), pos); } - function parseJSDocUnknownOrNullableType(): JSDocUnknownType | JSDocNullableType { + function parseJSDocUnknownOrNullableType(): AstJSDocUnknownType | AstJSDocNullableType { const pos = getNodePos(); // skip the ? nextToken(); @@ -3819,7 +2965,7 @@ namespace Parser { } } - function parseJSDocFunctionType(): JSDocFunctionType | TypeReferenceNode { + function parseJSDocFunctionType(): AstJSDocFunctionType | AstTypeReferenceNode { const pos = getNodePos(); const hasJSDoc = hasPrecedingJSDocComment(); if (tryParse(nextTokenIsOpenParen)) { @@ -3830,9 +2976,9 @@ namespace Parser { return finishNode(factory.createTypeReferenceNode(parseIdentifierName(), /*typeArguments*/ undefined), pos); } - function parseJSDocParameter(): ParameterDeclaration { + function parseJSDocParameter(): AstParameterDeclaration { const pos = getNodePos(); - let name: Identifier | undefined; + let name: AstIdentifier | undefined; if (token() === SyntaxKind.ThisKeyword || token() === SyntaxKind.NewKeyword) { name = parseIdentifierName(); parseExpected(SyntaxKind.ColonToken); @@ -3851,7 +2997,7 @@ namespace Parser { ); } - function parseJSDocType(): TypeNode { + function parseJSDocType(): AstTypeNode { scanner.setSkipJsDocLeadingAsterisks(true); const pos = getNodePos(); if (parseOptional(SyntaxKind.ModuleKeyword)) { @@ -3887,7 +3033,7 @@ namespace Parser { return type; } - function parseTypeQuery(): TypeQueryNode { + function parseTypeQuery(): AstTypeQueryNode { const pos = getNodePos(); parseExpected(SyntaxKind.TypeOfKeyword); const entityName = parseEntityName(/*allowReservedWords*/ true); @@ -3896,12 +3042,12 @@ namespace Parser { return finishNode(factory.createTypeQueryNode(entityName, typeArguments), pos); } - function parseTypeParameter(): TypeParameterDeclaration { + function parseTypeParameter(): AstTypeParameterDeclaration { const pos = getNodePos(); const modifiers = parseModifiers(/*allowDecorators*/ false, /*permitConstAsModifier*/ true); const name = parseIdentifier(); - let constraint: TypeNode | undefined; - let expression: Expression | undefined; + let constraint: AstTypeNode | undefined; + let expression: AstExpression | undefined; if (parseOptional(SyntaxKind.ExtendsKeyword)) { // It's not uncommon for people to write improper constraints to a generic. If the // user writes a constraint that is an expression and not an actual type, then parse @@ -3924,11 +3070,11 @@ namespace Parser { const defaultType = parseOptional(SyntaxKind.EqualsToken) ? parseType() : undefined; const node = factory.createTypeParameterDeclaration(modifiers, name, constraint, defaultType); - node.expression = expression; + node.data.expression = expression; return finishNode(node, pos); } - function parseTypeParameters(): NodeArray | undefined { + function parseTypeParameters(): AstNodeArray | undefined { if (token() === SyntaxKind.LessThanToken) { return parseBracketedList(ParsingContext.TypeParameters, parseTypeParameter, SyntaxKind.LessThanToken, SyntaxKind.GreaterThanToken); } @@ -3942,11 +3088,11 @@ namespace Parser { isStartOfType(/*inStartOfParameter*/ !isJSDocParameter); } - function parseNameOfParameter(modifiers: NodeArray | undefined) { + function parseNameOfParameter(modifiers: AstNodeArray | undefined) { // FormalParameter [Yield,Await]: // BindingElement[?Yield,?Await] const name = parseIdentifierOrPattern(Diagnostics.Private_identifiers_cannot_be_used_as_parameters); - if (getFullWidth(name) === 0 && !some(modifiers) && isModifierKind(token())) { + if (getFullWidth(name) === 0 && !some(modifiers?.items) && isModifierKind(token())) { // in cases like // 'use strict' // function foo(static) @@ -3967,17 +3113,17 @@ namespace Parser { return isBindingIdentifier() || token() === SyntaxKind.OpenBracketToken || token() === SyntaxKind.OpenBraceToken; } - function parseParameter(inOuterAwaitContext: boolean): ParameterDeclaration { + function parseParameter(inOuterAwaitContext: boolean): AstParameterDeclaration { return parseParameterWorker(inOuterAwaitContext); } - function parseParameterForSpeculation(inOuterAwaitContext: boolean): ParameterDeclaration | undefined { + function parseParameterForSpeculation(inOuterAwaitContext: boolean): AstParameterDeclaration | undefined { return parseParameterWorker(inOuterAwaitContext, /*allowAmbiguity*/ false); } - function parseParameterWorker(inOuterAwaitContext: boolean): ParameterDeclaration; - function parseParameterWorker(inOuterAwaitContext: boolean, allowAmbiguity: false): ParameterDeclaration | undefined; - function parseParameterWorker(inOuterAwaitContext: boolean, allowAmbiguity = true): ParameterDeclaration | undefined { + function parseParameterWorker(inOuterAwaitContext: boolean): AstParameterDeclaration; + function parseParameterWorker(inOuterAwaitContext: boolean, allowAmbiguity: false): AstParameterDeclaration | undefined; + function parseParameterWorker(inOuterAwaitContext: boolean, allowAmbiguity = true): AstParameterDeclaration | undefined { const pos = getNodePos(); const hasJSDoc = hasPrecedingJSDocComment(); @@ -3999,7 +3145,7 @@ namespace Parser { /*initializer*/ undefined, ); - const modifier = firstOrUndefined(modifiers); + const modifier = firstOrUndefined(modifiers?.items); if (modifier) { parseErrorAtRange(modifier, Diagnostics.Neither_decorators_nor_modifiers_may_be_applied_to_this_parameters); } @@ -4034,8 +3180,8 @@ namespace Parser { return node; } - function parseReturnType(returnToken: SyntaxKind.EqualsGreaterThanToken, isType: boolean): TypeNode; - function parseReturnType(returnToken: SyntaxKind.ColonToken | SyntaxKind.EqualsGreaterThanToken, isType: boolean): TypeNode | undefined; + function parseReturnType(returnToken: SyntaxKind.EqualsGreaterThanToken, isType: boolean): AstTypeNode; + function parseReturnType(returnToken: SyntaxKind.ColonToken | SyntaxKind.EqualsGreaterThanToken, isType: boolean): AstTypeNode | undefined; function parseReturnType(returnToken: SyntaxKind.ColonToken | SyntaxKind.EqualsGreaterThanToken, isType: boolean) { if (shouldParseReturnType(returnToken, isType)) { return allowConditionalTypesAnd(parseTypeOrTypePredicate); @@ -4059,9 +3205,9 @@ namespace Parser { return false; } - function parseParametersWorker(flags: SignatureFlags, allowAmbiguity: true): NodeArray; - function parseParametersWorker(flags: SignatureFlags, allowAmbiguity: false): NodeArray | undefined; - function parseParametersWorker(flags: SignatureFlags, allowAmbiguity: boolean): NodeArray | undefined { + function parseParametersWorker(flags: SignatureFlags, allowAmbiguity: true): AstNodeArray; + function parseParametersWorker(flags: SignatureFlags, allowAmbiguity: false): AstNodeArray | undefined; + function parseParametersWorker(flags: SignatureFlags, allowAmbiguity: boolean): AstNodeArray | undefined { // FormalParameters [Yield,Await]: (modified) // [empty] // FormalParameterList[?Yield,Await] @@ -4091,7 +3237,7 @@ namespace Parser { return parameters; } - function parseParameters(flags: SignatureFlags): NodeArray { + function parseParameters(flags: SignatureFlags): AstNodeArray { // FormalParameters [Yield,Await]: (modified) // [empty] // FormalParameterList[?Yield,Await] @@ -4106,7 +3252,7 @@ namespace Parser { // SingleNameBinding [Yield,Await]: // BindingIdentifier[?Yield,?Await]Initializer [In, ?Yield,?Await] opt if (!parseExpected(SyntaxKind.OpenParenToken)) { - return createMissingList(); + return createMissingList(); } const parameters = parseParametersWorker(flags, /*allowAmbiguity*/ true); @@ -4125,7 +3271,7 @@ namespace Parser { parseSemicolon(); } - function parseSignatureMember(kind: SyntaxKind.CallSignature | SyntaxKind.ConstructSignature): CallSignatureDeclaration | ConstructSignatureDeclaration { + function parseSignatureMember(kind: SyntaxKind.CallSignature | SyntaxKind.ConstructSignature): AstCallSignatureDeclaration | AstConstructSignatureDeclaration { const pos = getNodePos(); const hasJSDoc = hasPrecedingJSDocComment(); if (kind === SyntaxKind.ConstructSignature) { @@ -4201,18 +3347,18 @@ namespace Parser { return token() === SyntaxKind.ColonToken || token() === SyntaxKind.CommaToken || token() === SyntaxKind.CloseBracketToken; } - function parseIndexSignatureDeclaration(pos: number, hasJSDoc: boolean, modifiers: NodeArray | undefined): IndexSignatureDeclaration { - const parameters = parseBracketedList(ParsingContext.Parameters, () => parseParameter(/*inOuterAwaitContext*/ false), SyntaxKind.OpenBracketToken, SyntaxKind.CloseBracketToken); + function parseIndexSignatureDeclaration(pos: number, hasJSDoc: boolean, modifiers: AstNodeArray | undefined): AstIndexSignatureDeclaration { + const parameters = parseBracketedList(ParsingContext.Parameters, () => parseParameter(/*inOuterAwaitContext*/ false), SyntaxKind.OpenBracketToken, SyntaxKind.CloseBracketToken); const type = parseTypeAnnotation(); parseTypeMemberSemicolon(); const node = factory.createIndexSignature(modifiers, parameters, type); return withJSDoc(finishNode(node, pos), hasJSDoc); } - function parsePropertyOrMethodSignature(pos: number, hasJSDoc: boolean, modifiers: NodeArray | undefined): PropertySignature | MethodSignature { + function parsePropertyOrMethodSignature(pos: number, hasJSDoc: boolean, modifiers: AstNodeArray | undefined): AstPropertySignature | AstMethodSignature { const name = parsePropertyName(); const questionToken = parseOptionalToken(SyntaxKind.QuestionToken); - let node: PropertySignature | MethodSignature; + let node: AstPropertySignature | AstMethodSignature; if (token() === SyntaxKind.OpenParenToken || token() === SyntaxKind.LessThanToken) { // Method signatures don't exist in expression contexts. So they have neither // [Yield] nor [Await] @@ -4227,7 +3373,9 @@ namespace Parser { // Although type literal properties cannot not have initializers, we attempt // to parse an initializer so we can report in the checker that an interface // property or type literal property cannot have an initializer. - if (token() === SyntaxKind.EqualsToken) (node as Mutable).initializer = parseInitializer(); + if (token() === SyntaxKind.EqualsToken) { + node.data.initializer = parseInitializer(); + } } parseTypeMemberSemicolon(); return withJSDoc(finishNode(node, pos), hasJSDoc); @@ -4271,7 +3419,7 @@ namespace Parser { return false; } - function parseTypeMember(): TypeElement { + function parseTypeMember(): AstTypeElement { if (token() === SyntaxKind.OpenParenToken || token() === SyntaxKind.LessThanToken) { return parseSignatureMember(SyntaxKind.CallSignature); } @@ -4314,19 +3462,19 @@ namespace Parser { return false; } - function parseTypeLiteral(): TypeLiteralNode { + function parseTypeLiteral(): AstTypeLiteralNode { const pos = getNodePos(); return finishNode(factory.createTypeLiteralNode(parseObjectTypeMembers()), pos); } - function parseObjectTypeMembers(): NodeArray { - let members: NodeArray; + function parseObjectTypeMembers(): AstNodeArray { + let members: AstNodeArray; if (parseExpected(SyntaxKind.OpenBraceToken)) { members = parseList(ParsingContext.TypeMembers, parseTypeMember); parseExpected(SyntaxKind.CloseBraceToken); } else { - members = createMissingList(); + members = createMissingList(); } return members; @@ -4354,9 +3502,9 @@ namespace Parser { function parseMappedType() { const pos = getNodePos(); parseExpected(SyntaxKind.OpenBraceToken); - let readonlyToken: ReadonlyKeyword | PlusToken | MinusToken | undefined; + let readonlyToken: AstReadonlyKeyword | AstPlusToken | AstMinusToken | undefined; if (token() === SyntaxKind.ReadonlyKeyword || token() === SyntaxKind.PlusToken || token() === SyntaxKind.MinusToken) { - readonlyToken = parseTokenNode(); + readonlyToken = parseTokenNode(); if (readonlyToken.kind !== SyntaxKind.ReadonlyKeyword) { parseExpected(SyntaxKind.ReadonlyKeyword); } @@ -4365,9 +3513,9 @@ namespace Parser { const typeParameter = parseMappedTypeParameter(); const nameType = parseOptional(SyntaxKind.AsKeyword) ? parseType() : undefined; parseExpected(SyntaxKind.CloseBracketToken); - let questionToken: QuestionToken | PlusToken | MinusToken | undefined; + let questionToken: AstQuestionToken | AstPlusToken | AstMinusToken | undefined; if (token() === SyntaxKind.QuestionToken || token() === SyntaxKind.PlusToken || token() === SyntaxKind.MinusToken) { - questionToken = parseTokenNode(); + questionToken = parseTokenNode(); if (questionToken.kind !== SyntaxKind.QuestionToken) { parseExpected(SyntaxKind.QuestionToken); } @@ -4385,10 +3533,10 @@ namespace Parser { return finishNode(factory.createRestTypeNode(parseType()), pos); } const type = parseType(); - if (isJSDocNullableType(type) && type.pos === type.type.pos) { - const node = factory.createOptionalTypeNode(type.type); + if (isAstJSDocNullableType(type) && type.pos === type.data.type.pos) { + const node = factory.createOptionalTypeNode(type.data.type); setTextRange(node, type); - (node as Mutable).flags = type.flags; + node.flags = type.flags; return node; } return type; @@ -4420,7 +3568,7 @@ namespace Parser { return parseTupleElementType(); } - function parseTupleType(): TupleTypeNode { + function parseTupleType(): AstTupleTypeNode { const pos = getNodePos(); return finishNode( factory.createTupleTypeNode( @@ -4430,7 +3578,7 @@ namespace Parser { ); } - function parseParenthesizedType(): TypeNode { + function parseParenthesizedType(): AstTypeNode { const pos = getNodePos(); parseExpected(SyntaxKind.OpenParenToken); const type = parseType(); @@ -4438,18 +3586,18 @@ namespace Parser { return finishNode(factory.createParenthesizedType(type), pos); } - function parseModifiersForConstructorType(): NodeArray | undefined { - let modifiers: NodeArray | undefined; + function parseModifiersForConstructorType(): AstNodeArray | undefined { + let modifiers: AstNodeArray | undefined; if (token() === SyntaxKind.AbstractKeyword) { const pos = getNodePos(); nextToken(); const modifier = finishNode(factoryCreateToken(SyntaxKind.AbstractKeyword), pos); - modifiers = createNodeArray([modifier], pos); + modifiers = createNodeArray([modifier], pos); } return modifiers; } - function parseFunctionOrConstructorType(): TypeNode { + function parseFunctionOrConstructorType(): AstTypeNode { const pos = getNodePos(); const hasJSDoc = hasPrecedingJSDocComment(); const modifiers = parseModifiersForConstructorType(); @@ -4464,19 +3612,19 @@ namespace Parser { return withJSDoc(finishNode(node, pos), hasJSDoc); } - function parseKeywordAndNoDot(): TypeNode | undefined { - const node = parseTokenNode(); + function parseKeywordAndNoDot(): AstKeywordTypeNode | undefined { + const node = parseTokenNode(); return token() === SyntaxKind.DotToken ? undefined : node; } - function parseLiteralTypeNode(negative?: boolean): LiteralTypeNode { + function parseLiteralTypeNode(negative?: boolean): AstLiteralTypeNode { const pos = getNodePos(); if (negative) { nextToken(); } - let expression: BooleanLiteral | NullLiteral | LiteralExpression | PrefixUnaryExpression = token() === SyntaxKind.TrueKeyword || token() === SyntaxKind.FalseKeyword || token() === SyntaxKind.NullKeyword ? - parseTokenNode() : - parseLiteralLikeNode(token()) as LiteralExpression; + let expression: AstBooleanLiteral | AstNullLiteral | AstLiteralExpression | AstPrefixUnaryExpression = token() === SyntaxKind.TrueKeyword || token() === SyntaxKind.FalseKeyword || token() === SyntaxKind.NullKeyword ? + parseTokenNode() : + parseLiteralLikeNode(token()) as AstLiteralExpression; if (negative) { expression = finishNode(factory.createPrefixUnaryExpression(SyntaxKind.MinusToken, expression), pos); } @@ -4488,14 +3636,14 @@ namespace Parser { return token() === SyntaxKind.ImportKeyword; } - function parseImportType(): ImportTypeNode { + function parseImportType(): AstImportTypeNode { sourceFlags |= NodeFlags.PossiblyContainsDynamicImport; const pos = getNodePos(); const isTypeOf = parseOptional(SyntaxKind.TypeOfKeyword); parseExpected(SyntaxKind.ImportKeyword); parseExpected(SyntaxKind.OpenParenToken); const type = parseType(); - let attributes: ImportAttributes | undefined; + let attributes: AstImportAttributes | undefined; if (parseOptional(SyntaxKind.CommaToken)) { const openBracePosition = scanner.getTokenStart(); parseExpected(SyntaxKind.OpenBraceToken); @@ -4529,7 +3677,7 @@ namespace Parser { return token() === SyntaxKind.NumericLiteral || token() === SyntaxKind.BigIntLiteral; } - function parseNonArrayType(): TypeNode { + function parseNonArrayType(): AstTypeNode { switch (token()) { case SyntaxKind.AnyKeyword: case SyntaxKind.UnknownKeyword: @@ -4570,7 +3718,7 @@ namespace Parser { case SyntaxKind.MinusToken: return lookAhead(nextTokenIsNumericOrBigIntLiteral) ? parseLiteralTypeNode(/*negative*/ true) : parseTypeReference(); case SyntaxKind.VoidKeyword: - return parseTokenNode(); + return parseTokenNode(); case SyntaxKind.ThisKeyword: { const thisKeyword = parseThisTypeNode(); if (token() === SyntaxKind.IsKeyword && !scanner.hasPrecedingLineBreak()) { @@ -4656,7 +3804,7 @@ namespace Parser { return token() === SyntaxKind.CloseParenToken || isStartOfParameter(/*isJSDocParameter*/ false) || isStartOfType(); } - function parsePostfixTypeOrHigher(): TypeNode { + function parsePostfixTypeOrHigher(): AstTypeNode { const pos = getNodePos(); let type = parseNonArrayType(); while (!scanner.hasPrecedingLineBreak()) { @@ -4707,7 +3855,7 @@ namespace Parser { } } - function parseTypeParameterOfInferType(): TypeParameterDeclaration { + function parseTypeParameterOfInferType(): AstTypeParameterDeclaration { const pos = getNodePos(); const name = parseIdentifier(); const constraint = tryParse(tryParseConstraintOfInferType); @@ -4715,13 +3863,13 @@ namespace Parser { return finishNode(node, pos); } - function parseInferType(): InferTypeNode { + function parseInferType(): AstInferTypeNode { const pos = getNodePos(); parseExpected(SyntaxKind.InferKeyword); return finishNode(factory.createInferTypeNode(parseTypeParameterOfInferType()), pos); } - function parseTypeOperatorOrHigher(): TypeNode { + function parseTypeOperatorOrHigher(): AstTypeNode { const operator = token(); switch (operator) { case SyntaxKind.KeyOfKeyword: @@ -4736,14 +3884,14 @@ namespace Parser { function parseFunctionOrConstructorTypeToError( isInUnionType: boolean, - ): TypeNode | undefined { + ): AstTypeNode | undefined { // the function type and constructor type shorthand notation // are not allowed directly in unions and intersections, but we'll // try to parse them gracefully and issue a helpful message. if (isStartOfFunctionTypeOrConstructorType()) { const type = parseFunctionOrConstructorType(); let diagnostic: DiagnosticMessage; - if (isFunctionTypeNode(type)) { + if (isAstFunctionTypeNode(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; @@ -4761,9 +3909,9 @@ namespace Parser { function parseUnionOrIntersectionType( operator: SyntaxKind.BarToken | SyntaxKind.AmpersandToken, - parseConstituentType: () => TypeNode, - createTypeNode: (types: NodeArray) => UnionOrIntersectionTypeNode, - ): TypeNode { + parseConstituentType: () => AstTypeNode, + createTypeNode: (types: AstNodeArray) => AstUnionOrIntersectionTypeNode, + ): AstTypeNode { const pos = getNodePos(); const isUnionType = operator === SyntaxKind.BarToken; const hasLeadingOperator = parseOptional(operator); @@ -4779,11 +3927,11 @@ namespace Parser { return type; } - function parseIntersectionTypeOrHigher(): TypeNode { + function parseIntersectionTypeOrHigher(): AstTypeNode { return parseUnionOrIntersectionType(SyntaxKind.AmpersandToken, parseTypeOperatorOrHigher, factory.createIntersectionTypeNode); } - function parseUnionTypeOrHigher(): TypeNode { + function parseUnionTypeOrHigher(): AstTypeNode { return parseUnionOrIntersectionType(SyntaxKind.BarToken, parseIntersectionTypeOrHigher, factory.createUnionTypeNode); } @@ -4852,7 +4000,7 @@ namespace Parser { return false; } - function parseTypeOrTypePredicate(): TypeNode { + function parseTypeOrTypePredicate(): AstTypeNode { const pos = getNodePos(); const typePredicateVariable = isIdentifier() && tryParse(parseTypePredicatePrefix); const type = parseType(); @@ -4872,7 +4020,7 @@ namespace Parser { } } - function parseAssertsTypePredicate(): TypeNode { + function parseAssertsTypePredicate(): AstTypeNode { const pos = getNodePos(); const assertsModifier = parseExpectedToken(SyntaxKind.AssertsKeyword); const parameterName = token() === SyntaxKind.ThisKeyword ? parseThisTypeNode() : parseIdentifier(); @@ -4880,7 +4028,7 @@ namespace Parser { return finishNode(factory.createTypePredicateNode(assertsModifier, parameterName, type), pos); } - function parseType(): TypeNode { + function parseType(): AstTypeNode { if (contextFlags & NodeFlags.TypeExcludesFlags) { return doOutsideOfContext(NodeFlags.TypeExcludesFlags, parseType); } @@ -4901,7 +4049,7 @@ namespace Parser { return type; } - function parseTypeAnnotation(): TypeNode | undefined { + function parseTypeAnnotation(): AstTypeNode | undefined { return parseOptional(SyntaxKind.ColonToken) ? parseType() : undefined; } @@ -4981,7 +4129,7 @@ namespace Parser { isStartOfExpression(); } - function parseExpression(): Expression { + function parseExpression(): AstExpression { // Expression[in]: // AssignmentExpression[in] // Expression[in] , AssignmentExpression[in] @@ -4994,7 +4142,7 @@ namespace Parser { const pos = getNodePos(); let expr = parseAssignmentExpressionOrHigher(/*allowReturnTypeInArrowFunction*/ true); - let operatorToken: BinaryOperatorToken; + let operatorToken: AstBinaryOperatorToken; while ((operatorToken = parseOptionalToken(SyntaxKind.CommaToken))) { expr = makeBinaryExpression(expr, operatorToken, parseAssignmentExpressionOrHigher(/*allowReturnTypeInArrowFunction*/ true), pos); } @@ -5005,11 +4153,11 @@ namespace Parser { return expr; } - function parseInitializer(): Expression | undefined { + function parseInitializer(): AstExpression | undefined { return parseOptional(SyntaxKind.EqualsToken) ? parseAssignmentExpressionOrHigher(/*allowReturnTypeInArrowFunction*/ true) : undefined; } - function parseAssignmentExpressionOrHigher(allowReturnTypeInArrowFunction: boolean): Expression { + function parseAssignmentExpressionOrHigher(allowReturnTypeInArrowFunction: boolean): AstExpression { // AssignmentExpression[in,yield]: // 1) ConditionalExpression[?in,?yield] // 2) LeftHandSideExpression = AssignmentExpression[?in,?yield] @@ -5059,7 +4207,7 @@ namespace Parser { // parameter ('x => ...') above. We handle it here by checking if the parsed expression was a single // identifier and the current token is an arrow. if (expr.kind === SyntaxKind.Identifier && token() === SyntaxKind.EqualsGreaterThanToken) { - return parseSimpleArrowFunctionExpression(pos, expr as Identifier, allowReturnTypeInArrowFunction, hasJSDoc, /*asyncModifier*/ undefined); + return parseSimpleArrowFunctionExpression(pos, expr as AstIdentifier, allowReturnTypeInArrowFunction, hasJSDoc, /*asyncModifier*/ undefined); } // Now see if we might be in cases '2' or '3'. @@ -5068,7 +4216,7 @@ namespace Parser { // // Note: we call reScanGreaterToken so that we get an appropriately merged token // for cases like `> > =` becoming `>>=` - if (isLeftHandSideExpression(expr) && isAssignmentOperator(reScanGreaterToken())) { + if (isAstLeftHandSideExpression(expr) && isAssignmentOperator(reScanGreaterToken())) { return makeBinaryExpression(expr, parseTokenNode(), parseAssignmentExpressionOrHigher(allowReturnTypeInArrowFunction), pos); } @@ -5109,7 +4257,7 @@ namespace Parser { return !scanner.hasPrecedingLineBreak() && isIdentifier(); } - function parseYieldExpression(): YieldExpression { + function parseYieldExpression(): AstYieldExpression { const pos = getNodePos(); // YieldExpression[In] : @@ -5137,7 +4285,7 @@ namespace Parser { } } - function parseSimpleArrowFunctionExpression(pos: number, identifier: Identifier, allowReturnTypeInArrowFunction: boolean, hasJSDoc: boolean, asyncModifier?: NodeArray | undefined): ArrowFunction { + function parseSimpleArrowFunctionExpression(pos: number, identifier: AstIdentifier, allowReturnTypeInArrowFunction: boolean, hasJSDoc: boolean, asyncModifier?: AstNodeArray | undefined): AstArrowFunction { Debug.assert(token() === SyntaxKind.EqualsGreaterThanToken, "parseSimpleArrowFunctionExpression should only have been called if we had a =>"); const parameter = factory.createParameterDeclaration( /*modifiers*/ undefined, @@ -5149,14 +4297,14 @@ namespace Parser { ); finishNode(parameter, identifier.pos); - const parameters = createNodeArray([parameter], parameter.pos, parameter.end); + const parameters = createNodeArray([parameter], parameter.pos, parameter.end); const equalsGreaterThanToken = parseExpectedToken(SyntaxKind.EqualsGreaterThanToken); const body = parseArrowFunctionExpressionBody(/*isAsync*/ !!asyncModifier, allowReturnTypeInArrowFunction); const node = factory.createArrowFunction(asyncModifier, /*typeParameters*/ undefined, parameters, /*type*/ undefined, equalsGreaterThanToken, body); return withJSDoc(finishNode(node, pos), hasJSDoc); } - function tryParseParenthesizedArrowFunctionExpression(allowReturnTypeInArrowFunction: boolean): Expression | undefined { + function tryParseParenthesizedArrowFunctionExpression(allowReturnTypeInArrowFunction: boolean): AstExpression | undefined { const triState = isParenthesizedArrowFunctionExpression(); if (triState === Tristate.False) { // It's definitely not a parenthesized arrow function expression. @@ -5321,7 +4469,7 @@ namespace Parser { } } - function parsePossibleParenthesizedArrowFunctionExpression(allowReturnTypeInArrowFunction: boolean): ArrowFunction | undefined { + function parsePossibleParenthesizedArrowFunctionExpression(allowReturnTypeInArrowFunction: boolean): AstArrowFunction | undefined { const tokenPos = scanner.getTokenStart(); if (notParenthesizedArrow?.has(tokenPos)) { return undefined; @@ -5335,7 +4483,7 @@ namespace Parser { return result; } - function tryParseAsyncSimpleArrowFunctionExpression(allowReturnTypeInArrowFunction: boolean): ArrowFunction | undefined { + function tryParseAsyncSimpleArrowFunctionExpression(allowReturnTypeInArrowFunction: boolean): AstArrowFunction | undefined { // We do a check here so that we won't be doing unnecessarily call to "lookAhead" if (token() === SyntaxKind.AsyncKeyword) { if (lookAhead(isUnParenthesizedAsyncArrowFunctionWorker) === Tristate.True) { @@ -5343,7 +4491,7 @@ namespace Parser { const hasJSDoc = hasPrecedingJSDocComment(); const asyncModifier = parseModifiersForArrowFunction(); const expr = parseBinaryExpressionOrHigher(OperatorPrecedence.Lowest); - return parseSimpleArrowFunctionExpression(pos, expr as Identifier, allowReturnTypeInArrowFunction, hasJSDoc, asyncModifier); + return parseSimpleArrowFunctionExpression(pos, expr as AstIdentifier, allowReturnTypeInArrowFunction, hasJSDoc, asyncModifier); } } return undefined; @@ -5370,11 +4518,11 @@ namespace Parser { return Tristate.False; } - function parseParenthesizedArrowFunctionExpression(allowAmbiguity: boolean, allowReturnTypeInArrowFunction: boolean): ArrowFunction | undefined { + function parseParenthesizedArrowFunctionExpression(allowAmbiguity: boolean, allowReturnTypeInArrowFunction: boolean): AstArrowFunction | undefined { const pos = getNodePos(); const hasJSDoc = hasPrecedingJSDocComment(); const modifiers = parseModifiersForArrowFunction(); - const isAsync = some(modifiers, isAsyncModifier) ? SignatureFlags.Await : SignatureFlags.None; + const isAsync = some(modifiers?.items, isAstAsyncModifier) ? SignatureFlags.Await : SignatureFlags.None; // Arrow functions are never generators. // // If we're speculatively parsing a signature for a parenthesized arrow function, then @@ -5384,12 +4532,12 @@ namespace Parser { // close paren. const typeParameters = parseTypeParameters(); - let parameters: NodeArray; + let parameters: AstNodeArray; if (!parseExpected(SyntaxKind.OpenParenToken)) { if (!allowAmbiguity) { return undefined; } - parameters = createMissingList(); + parameters = createMissingList(); } else { if (!allowAmbiguity) { @@ -5426,10 +4574,10 @@ namespace Parser { let unwrappedType = type; while (unwrappedType?.kind === SyntaxKind.ParenthesizedType) { - unwrappedType = (unwrappedType as ParenthesizedTypeNode).type; // Skip parens if need be + unwrappedType = (unwrappedType as AstParenthesizedTypeNode).data.type; // Skip parens if need be } - const hasJSDocFunctionType = unwrappedType && isJSDocFunctionType(unwrappedType); + const hasJSDocFunctionType = unwrappedType && isAstJSDocFunctionType(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; @@ -5440,7 +4588,7 @@ namespace Parser { const lastToken = token(); const equalsGreaterThanToken = parseExpectedToken(SyntaxKind.EqualsGreaterThanToken); const body = (lastToken === SyntaxKind.EqualsGreaterThanToken || lastToken === SyntaxKind.OpenBraceToken) - ? parseArrowFunctionExpressionBody(some(modifiers, isAsyncModifier), allowReturnTypeInArrowFunction) + ? parseArrowFunctionExpressionBody(some(modifiers?.items, isAstAsyncModifier), allowReturnTypeInArrowFunction) : parseIdentifier(); // Given: @@ -5473,7 +4621,7 @@ namespace Parser { return withJSDoc(finishNode(node, pos), hasJSDoc); } - function parseArrowFunctionExpressionBody(isAsync: boolean, allowReturnTypeInArrowFunction: boolean): Block | Expression { + function parseArrowFunctionExpressionBody(isAsync: boolean, allowReturnTypeInArrowFunction: boolean): AstConciseBody { if (token() === SyntaxKind.OpenBraceToken) { return parseFunctionBlock(isAsync ? SignatureFlags.Await : SignatureFlags.None); } @@ -5511,7 +4659,7 @@ namespace Parser { return node; } - function parseConditionalExpressionRest(leftOperand: Expression, pos: number, allowReturnTypeInArrowFunction: boolean): Expression { + function parseConditionalExpressionRest(leftOperand: AstExpression, pos: number, allowReturnTypeInArrowFunction: boolean): AstExpression { // Note: we are passed in an expression which was produced from parseBinaryExpressionOrHigher. const questionToken = parseOptionalToken(SyntaxKind.QuestionToken); if (!questionToken) { @@ -5535,7 +4683,7 @@ namespace Parser { ); } - function parseBinaryExpressionOrHigher(precedence: OperatorPrecedence): Expression { + function parseBinaryExpressionOrHigher(precedence: OperatorPrecedence): AstExpression { const pos = getNodePos(); const leftOperand = parseUnaryExpressionOrHigher(); return parseBinaryExpressionRest(precedence, leftOperand, pos); @@ -5545,7 +4693,7 @@ namespace Parser { return t === SyntaxKind.InKeyword || t === SyntaxKind.OfKeyword; } - function parseBinaryExpressionRest(precedence: OperatorPrecedence, leftOperand: Expression, pos: number): Expression { + function parseBinaryExpressionRest(precedence: OperatorPrecedence, leftOperand: AstExpression, pos: number): AstExpression { while (true) { // We either have a binary operator here, or we're finished. We call // reScanGreaterToken so that we merge token sequences like > and = into >= @@ -5618,15 +4766,15 @@ namespace Parser { return getBinaryOperatorPrecedence(token()) > 0; } - function makeSatisfiesExpression(left: Expression, right: TypeNode): SatisfiesExpression { + function makeSatisfiesExpression(left: AstExpression, right: AstTypeNode): AstSatisfiesExpression { return finishNode(factory.createSatisfiesExpression(left, right), left.pos); } - function makeBinaryExpression(left: Expression, operatorToken: BinaryOperatorToken, right: Expression, pos: number): BinaryExpression { + function makeBinaryExpression(left: AstExpression, operatorToken: AstBinaryOperatorToken, right: AstExpression, pos: number): AstBinaryExpression { return finishNode(factory.createBinaryExpression(left, operatorToken, right), pos); } - function makeAsExpression(left: Expression, right: TypeNode): AsExpression { + function makeAsExpression(left: AstExpression, right: AstTypeNode): AstAsExpression { return finishNode(factory.createAsExpression(left, right), left.pos); } @@ -5675,7 +4823,7 @@ namespace Parser { * 1) UnaryExpression[?Yield] * 2) UpdateExpression[?Yield] ** ExponentiationExpression[?Yield] */ - function parseUnaryExpressionOrHigher(): UnaryExpression | BinaryExpression { + function parseUnaryExpressionOrHigher(): AstUnaryExpression | AstBinaryExpression { /** * ES7 UpdateExpression: * 1) LeftHandSideExpression[?Yield] @@ -5688,7 +4836,7 @@ namespace Parser { const pos = getNodePos(); const updateExpression = parseUpdateExpression(); return token() === SyntaxKind.AsteriskAsteriskToken ? - parseBinaryExpressionRest(getBinaryOperatorPrecedence(token()), updateExpression, pos) as BinaryExpression : + parseBinaryExpressionRest(getBinaryOperatorPrecedence(token()), updateExpression, pos) as AstBinaryExpression : updateExpression; } @@ -5733,7 +4881,7 @@ namespace Parser { * 8) ! UnaryExpression[?yield] * 9) [+Await] await UnaryExpression[?yield] */ - function parseSimpleUnaryExpression(): UnaryExpression { + function parseSimpleUnaryExpression(): AstUnaryExpression { switch (token()) { case SyntaxKind.PlusToken: case SyntaxKind.MinusToken: @@ -5812,7 +4960,7 @@ namespace Parser { * 5) --LeftHandSideExpression[?yield] * In TypeScript (2), (3) are parsed as PostfixUnaryExpression. (4), (5) are parsed as PrefixUnaryExpression */ - function parseUpdateExpression(): UpdateExpression { + function parseUpdateExpression(): AstUpdateExpression { if (token() === SyntaxKind.PlusPlusToken || token() === SyntaxKind.MinusMinusToken) { const pos = getNodePos(); return finishNode(factory.createPrefixUnaryExpression(token() as PrefixUnaryOperator, nextTokenAnd(parseLeftHandSideExpressionOrHigher)), pos); @@ -5824,7 +4972,7 @@ namespace Parser { const expression = parseLeftHandSideExpressionOrHigher(); - Debug.assert(isLeftHandSideExpression(expression)); + Debug.assert(isAstLeftHandSideExpression(expression)); if ((token() === SyntaxKind.PlusPlusToken || token() === SyntaxKind.MinusMinusToken) && !scanner.hasPrecedingLineBreak()) { const operator = token() as PostfixUnaryOperator; nextToken(); @@ -5834,7 +4982,7 @@ namespace Parser { return expression; } - function parseLeftHandSideExpressionOrHigher(): LeftHandSideExpression { + function parseLeftHandSideExpressionOrHigher(): AstLeftHandSideExpression { // Original Ecma: // LeftHandSideExpression: See 11.2 // NewExpression @@ -5867,7 +5015,7 @@ namespace Parser { // 3)we have a MemberExpression which either completes the LeftHandSideExpression, // or starts the beginning of the first four CallExpression productions. const pos = getNodePos(); - let expression: MemberExpression; + let expression: AstMemberExpression; if (token() === SyntaxKind.ImportKeyword) { if (lookAhead(nextTokenIsOpenParenOrLessThan)) { // We don't want to eagerly consume all import keyword as import call expression so we look ahead to find "(" @@ -5876,7 +5024,7 @@ namespace Parser { // import * as foo1 from "module-from-node // We want this import to be a statement rather than import call expression sourceFlags |= NodeFlags.PossiblyContainsDynamicImport; - expression = parseTokenNode(); + expression = parseTokenNode(); } else if (lookAhead(nextTokenIsDot)) { // This is an 'import.*' metaproperty (i.e. 'import.meta') @@ -5899,7 +5047,7 @@ namespace Parser { return parseCallExpressionRest(pos, expression); } - function parseMemberExpressionOrHigher(): MemberExpression { + function parseMemberExpressionOrHigher(): AstMemberExpression { // Note: to make our lives simpler, we decompose the NewExpression productions and // place ObjectCreationExpression and FunctionExpression into PrimaryExpression. // like so: @@ -5952,9 +5100,9 @@ namespace Parser { return parseMemberExpressionRest(pos, expression, /*allowOptionalChain*/ true); } - function parseSuperExpression(): MemberExpression { + function parseSuperExpression(): AstMemberExpression { const pos = getNodePos(); - let expression = parseTokenNode(); + let expression: AstMemberExpression = parseTokenNode(); if (token() === SyntaxKind.LessThanToken) { const startPos = getNodePos(); const typeArguments = tryParse(parseTypeArgumentsInExpression); @@ -5977,47 +5125,47 @@ namespace Parser { return finishNode(factoryCreatePropertyAccessExpression(expression, parseRightSideOfDot(/*allowIdentifierNames*/ true, /*allowPrivateIdentifiers*/ true, /*allowUnicodeEscapeSequenceInIdentifierName*/ true)), pos); } - function parseJsxElementOrSelfClosingElementOrFragment(inExpressionContext: boolean, topInvalidNodePosition?: number, openingTag?: JsxOpeningElement | JsxOpeningFragment, mustBeUnary = false): JsxElement | JsxSelfClosingElement | JsxFragment { + function parseJsxElementOrSelfClosingElementOrFragment(inExpressionContext: boolean, topInvalidNodePosition?: number, openingTag?: AstJsxOpeningElement | AstJsxOpeningFragment, mustBeUnary = false): AstJsxElement | AstJsxSelfClosingElement | AstJsxFragment { const pos = getNodePos(); const opening = parseJsxOpeningOrSelfClosingElementOrOpeningFragment(inExpressionContext); - let result: JsxElement | JsxSelfClosingElement | JsxFragment; + let result: AstJsxElement | AstJsxSelfClosingElement | AstJsxFragment; if (opening.kind === SyntaxKind.JsxOpeningElement) { let children = parseJsxChildren(opening); - let closingElement: JsxClosingElement; + let closingElement: AstJsxClosingElement; - const lastChild: JsxChild | undefined = children[children.length - 1]; + const lastChild: AstJsxChild | undefined = children.items[children.items.length - 1]; if ( lastChild?.kind === SyntaxKind.JsxElement - && !tagNamesAreEquivalent(lastChild.openingElement.tagName, lastChild.closingElement.tagName) - && tagNamesAreEquivalent(opening.tagName, lastChild.closingElement.tagName) + && !tagNamesAreEquivalent(lastChild.data.openingElement.data.tagName, lastChild.data.closingElement.data.tagName) + && tagNamesAreEquivalent(opening.data.tagName, lastChild.data.closingElement.data.tagName) ) { // when an unclosed JsxOpeningElement incorrectly parses its parent's JsxClosingElement, // restructure (
(......
)) --> (
(......)
) // (no need to error; the parent will error) - const end = lastChild.children.end; + const end = lastChild.data.children.end; const newLast = finishNode( factory.createJsxElement( - lastChild.openingElement, - lastChild.children, + lastChild.data.openingElement, + lastChild.data.children, finishNode(factory.createJsxClosingElement(finishNode(factoryCreateIdentifier(""), end, end)), end, end), ), - lastChild.openingElement.pos, + lastChild.data.openingElement.pos, end, ); - children = createNodeArray([...children.slice(0, children.length - 1), newLast], children.pos, end); - closingElement = lastChild.closingElement; + children = createNodeArray([...children.items.slice(0, children.items.length - 1), newLast], children.pos, end); + closingElement = lastChild.data.closingElement; } else { closingElement = parseJsxClosingElement(opening, inExpressionContext); - if (!tagNamesAreEquivalent(opening.tagName, closingElement.tagName)) { - if (openingTag && isJsxOpeningElement(openingTag) && tagNamesAreEquivalent(closingElement.tagName, openingTag.tagName)) { + if (!tagNamesAreEquivalent(opening.data.tagName, closingElement.data.tagName)) { + if (openingTag && isAstJsxOpeningElement(openingTag) && tagNamesAreEquivalent(closingElement.data.tagName, openingTag.data.tagName)) { // opening incorrectly matched with its parent's closing -- put error on opening - parseErrorAtRange(opening.tagName, Diagnostics.JSX_element_0_has_no_corresponding_closing_tag, getTextOfNodeFromSourceText(sourceText, opening.tagName)); + parseErrorAtRange(opening.data.tagName, Diagnostics.JSX_element_0_has_no_corresponding_closing_tag, getTextOfNodeFromSourceText(sourceText, opening.data.tagName)); } else { // other opening/closing mismatches -- put error on closing - parseErrorAtRange(closingElement.tagName, Diagnostics.Expected_corresponding_JSX_closing_tag_for_0, getTextOfNodeFromSourceText(sourceText, opening.tagName)); + parseErrorAtRange(closingElement.data.tagName, Diagnostics.Expected_corresponding_JSX_closing_tag_for_0, getTextOfNodeFromSourceText(sourceText, opening.data.tagName)); } } } @@ -6048,34 +5196,35 @@ namespace Parser { const operatorToken = createMissingNode(SyntaxKind.CommaToken, /*reportAtCurrentPosition*/ false); setTextRangePosWidth(operatorToken, invalidElement.pos, 0); parseErrorAt(skipTrivia(sourceText, topBadPos), invalidElement.end, Diagnostics.JSX_expressions_must_have_one_parent_element); - return finishNode(factory.createBinaryExpression(result, operatorToken as Token, invalidElement), pos) as Node as JsxElement; + // TODO(rbuckton): We shouldn't lie to the type system here and should allow BinaryExpression here or do something else less hacky + return finishNode(factory.createBinaryExpression(result, operatorToken as AstToken, invalidElement), pos) as AstNode as AstJsxElement; } } return result; } - function parseJsxText(): JsxText { + function parseJsxText(): AstJsxText { const pos = getNodePos(); const node = factory.createJsxText(scanner.getTokenValue(), currentToken === SyntaxKind.JsxTextAllWhiteSpaces); currentToken = scanner.scanJsxToken(); return finishNode(node, pos); } - function parseJsxChild(openingTag: JsxOpeningElement | JsxOpeningFragment, token: JsxTokenSyntaxKind): JsxChild | undefined { + function parseJsxChild(openingTag: AstJsxOpeningElement | AstJsxOpeningFragment, token: JsxTokenSyntaxKind): AstJsxChild | undefined { switch (token) { 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 (isJsxOpeningFragment(openingTag)) { + if (isAstJsxOpeningFragment(openingTag)) { parseErrorAtRange(openingTag, Diagnostics.JSX_fragment_has_no_corresponding_closing_tag); } else { // We want the error span to cover only 'Foo.Bar' in < Foo.Bar > // or to cover only 'Foo' in < Foo > - const tag = openingTag.tagName; + 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.tagName)); + parseErrorAt(start, tag.end, Diagnostics.JSX_element_0_has_no_corresponding_closing_tag, getTextOfNodeFromSourceText(sourceText, openingTag.data.tagName)); } return undefined; case SyntaxKind.LessThanSlashToken: @@ -6093,7 +5242,7 @@ namespace Parser { } } - function parseJsxChildren(openingTag: JsxOpeningElement | JsxOpeningFragment): NodeArray { + function parseJsxChildren(openingTag: AstJsxOpeningElement | AstJsxOpeningFragment): AstNodeArray { const list = []; const listPos = getNodePos(); const saveParsingContext = parsingContext; @@ -6104,10 +5253,10 @@ namespace Parser { if (!child) break; list.push(child); if ( - isJsxOpeningElement(openingTag) + isAstJsxOpeningElement(openingTag) && child?.kind === SyntaxKind.JsxElement - && !tagNamesAreEquivalent(child.openingElement.tagName, child.closingElement.tagName) - && tagNamesAreEquivalent(openingTag.tagName, child.closingElement.tagName) + && !tagNamesAreEquivalent(child.data.openingElement.data.tagName, child.data.closingElement.data.tagName) + && tagNamesAreEquivalent(openingTag.data.tagName, child.data.closingElement.data.tagName) ) { // stop after parsing a mismatched child like
...(
) in order to reattach the higher break; @@ -6118,12 +5267,12 @@ namespace Parser { return createNodeArray(list, listPos); } - function parseJsxAttributes(): JsxAttributes { + function parseJsxAttributes(): AstJsxAttributes { const pos = getNodePos(); return finishNode(factory.createJsxAttributes(parseList(ParsingContext.JsxAttributes, parseJsxAttribute)), pos); } - function parseJsxOpeningOrSelfClosingElementOrOpeningFragment(inExpressionContext: boolean): JsxOpeningElement | JsxSelfClosingElement | JsxOpeningFragment { + function parseJsxOpeningOrSelfClosingElementOrOpeningFragment(inExpressionContext: boolean): AstJsxOpeningElement | AstJsxSelfClosingElement | AstJsxOpeningFragment { const pos = getNodePos(); parseExpected(SyntaxKind.LessThanToken); @@ -6137,7 +5286,7 @@ namespace Parser { const typeArguments = (contextFlags & NodeFlags.JavaScriptFile) === 0 ? tryParseTypeArguments() : undefined; const attributes = parseJsxAttributes(); - let node: JsxOpeningLikeElement; + let node: AstJsxOpeningLikeElement; if (token() === SyntaxKind.GreaterThanToken) { // Closing tag, so scan the immediately-following text with the JSX scanning instead @@ -6163,7 +5312,7 @@ namespace Parser { return finishNode(node, pos); } - function parseJsxElementName(): JsxTagNameExpression { + function parseJsxElementName(): AstJsxTagNameExpression { const pos = getNodePos(); // JsxElement can have name in the form of // propertyAccessExpression @@ -6171,17 +5320,17 @@ 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 (isJsxNamespacedName(initialExpression)) { + if (isAstJsxNamespacedName(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: PropertyAccessExpression | Identifier | ThisExpression = initialExpression; + let expression: AstPropertyAccessExpression | AstIdentifier | AstThisExpression = initialExpression; while (parseOptional(SyntaxKind.DotToken)) { expression = finishNode(factoryCreatePropertyAccessExpression(expression, parseRightSideOfDot(/*allowIdentifierNames*/ true, /*allowPrivateIdentifiers*/ false, /*allowUnicodeEscapeSequenceInIdentifierName*/ false)), pos); } - return expression as JsxTagNameExpression; + return expression as AstJsxTagNameExpression; } - function parseJsxTagName(): Identifier | JsxNamespacedName | ThisExpression { + function parseJsxTagName(): AstIdentifier | AstJsxNamespacedName | AstThisExpression { const pos = getNodePos(); scanJsxIdentifier(); @@ -6194,14 +5343,14 @@ namespace Parser { return isThis ? finishNode(factory.createToken(SyntaxKind.ThisKeyword), pos) : tagName; } - function parseJsxExpression(inExpressionContext: boolean): JsxExpression | undefined { + function parseJsxExpression(inExpressionContext: boolean): AstJsxExpression | undefined { const pos = getNodePos(); if (!parseExpected(SyntaxKind.OpenBraceToken)) { return undefined; } - let dotDotDotToken: DotDotDotToken | undefined; - let expression: Expression | undefined; + let dotDotDotToken: AstDotDotDotToken | undefined; + let expression: AstExpression | undefined; if (token() !== SyntaxKind.CloseBraceToken) { if (!inExpressionContext) { dotDotDotToken = parseOptionalToken(SyntaxKind.DotDotDotToken); @@ -6223,7 +5372,7 @@ namespace Parser { return finishNode(factory.createJsxExpression(dotDotDotToken, expression), pos); } - function parseJsxAttribute(): JsxAttribute | JsxSpreadAttribute { + function parseJsxAttribute(): AstJsxAttribute | AstJsxSpreadAttribute { if (token() === SyntaxKind.OpenBraceToken) { return parseJsxSpreadAttribute(); } @@ -6232,10 +5381,10 @@ namespace Parser { return finishNode(factory.createJsxAttribute(parseJsxAttributeName(), parseJsxAttributeValue()), pos); } - function parseJsxAttributeValue(): JsxAttributeValue | undefined { + function parseJsxAttributeValue(): AstJsxAttributeValue | undefined { if (token() === SyntaxKind.EqualsToken) { if (scanJsxAttributeValue() === SyntaxKind.StringLiteral) { - return parseLiteralNode() as StringLiteral; + return parseLiteralNode() as AstStringLiteral; } if (token() === SyntaxKind.OpenBraceToken) { return parseJsxExpression(/*inExpressionContext*/ true); @@ -6260,7 +5409,7 @@ namespace Parser { return attrName; } - function parseJsxSpreadAttribute(): JsxSpreadAttribute { + function parseJsxSpreadAttribute(): AstJsxSpreadAttribute { const pos = getNodePos(); parseExpected(SyntaxKind.OpenBraceToken); parseExpected(SyntaxKind.DotDotDotToken); @@ -6269,13 +5418,13 @@ namespace Parser { return finishNode(factory.createJsxSpreadAttribute(expression), pos); } - function parseJsxClosingElement(open: JsxOpeningElement, inExpressionContext: boolean): JsxClosingElement { + function parseJsxClosingElement(open: AstJsxOpeningElement, inExpressionContext: boolean): AstJsxClosingElement { const pos = getNodePos(); parseExpected(SyntaxKind.LessThanSlashToken); const tagName = parseJsxElementName(); if (parseExpected(SyntaxKind.GreaterThanToken, /*diagnosticMessage*/ undefined, /*shouldAdvance*/ false)) { // manually advance the scanner in order to look for jsx text inside jsx - if (inExpressionContext || !tagNamesAreEquivalent(open.tagName, tagName)) { + if (inExpressionContext || !tagNamesAreEquivalent(open.data.tagName, tagName)) { nextToken(); } else { @@ -6285,7 +5434,7 @@ namespace Parser { return finishNode(factory.createJsxClosingElement(tagName), pos); } - function parseJsxClosingFragment(inExpressionContext: boolean): JsxClosingFragment { + function parseJsxClosingFragment(inExpressionContext: boolean): AstJsxClosingFragment { const pos = getNodePos(); parseExpected(SyntaxKind.LessThanSlashToken); if (parseExpected(SyntaxKind.GreaterThanToken, Diagnostics.Expected_corresponding_closing_tag_for_JSX_fragment, /*shouldAdvance*/ false)) { @@ -6297,10 +5446,10 @@ namespace Parser { scanJsxText(); } } - return finishNode(factory.createJsxJsxClosingFragment(), pos); + return finishNode(factory.createJsxClosingFragment(), pos); } - function parseTypeAssertion(): TypeAssertion { + function parseTypeAssertion(): AstTypeAssertion { Debug.assert(languageVariant !== LanguageVariant.JSX, "Type assertions should never be parsed in JSX; they should be parsed as comparisons or JSX elements/fragments."); const pos = getNodePos(); parseExpected(SyntaxKind.LessThanToken); @@ -6322,21 +5471,21 @@ namespace Parser { && lookAhead(nextTokenIsIdentifierOrKeywordOrOpenBracketOrTemplate); } - function tryReparseOptionalChain(node: Expression) { + function tryReparseOptionalChain(node: AstExpression) { if (node.flags & NodeFlags.OptionalChain) { return true; } // check for an optional chain in a non-null expression - if (isNonNullExpression(node)) { - let expr = node.expression; - while (isNonNullExpression(expr) && !(expr.flags & NodeFlags.OptionalChain)) { - expr = expr.expression; + if (isAstNonNullExpression(node)) { + let expr = node.data.expression; + while (isAstNonNullExpression(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 (isNonNullExpression(node)) { - (node as Mutable).flags |= NodeFlags.OptionalChain; - node = node.expression; + while (isAstNonNullExpression(node)) { + node.flags |= NodeFlags.OptionalChain; + node = node.data.expression; } return true; } @@ -6344,32 +5493,32 @@ namespace Parser { return false; } - function parsePropertyAccessExpressionRest(pos: number, expression: LeftHandSideExpression, questionDotToken: QuestionDotToken | undefined) { + function parsePropertyAccessExpressionRest(pos: number, expression: AstLeftHandSideExpression, questionDotToken: AstQuestionDotToken | undefined) { const name = parseRightSideOfDot(/*allowIdentifierNames*/ true, /*allowPrivateIdentifiers*/ true, /*allowUnicodeEscapeSequenceInIdentifierName*/ true); const isOptionalChain = questionDotToken || tryReparseOptionalChain(expression); const propertyAccess = isOptionalChain ? factoryCreatePropertyAccessChain(expression, questionDotToken, name) : factoryCreatePropertyAccessExpression(expression, name); - if (isOptionalChain && isPrivateIdentifier(propertyAccess.name)) { - parseErrorAtRange(propertyAccess.name, Diagnostics.An_optional_chain_cannot_contain_private_identifiers); + if (isOptionalChain && isAstPrivateIdentifier(propertyAccess.data.name)) { + parseErrorAtRange(propertyAccess.data.name, Diagnostics.An_optional_chain_cannot_contain_private_identifiers); } - if (isExpressionWithTypeArguments(expression) && expression.typeArguments) { - const pos = expression.typeArguments.pos - 1; - const end = skipTrivia(sourceText, expression.typeArguments.end) + 1; + if (isAstExpressionWithTypeArguments(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); } return finishNode(propertyAccess, pos); } - function parseElementAccessExpressionRest(pos: number, expression: LeftHandSideExpression, questionDotToken: QuestionDotToken | undefined) { - let argumentExpression: Expression; + function parseElementAccessExpressionRest(pos: number, expression: AstLeftHandSideExpression, questionDotToken: AstQuestionDotToken | undefined) { + let argumentExpression: AstExpression; if (token() === SyntaxKind.CloseBracketToken) { argumentExpression = createMissingNode(SyntaxKind.Identifier, /*reportAtCurrentPosition*/ true, Diagnostics.An_element_access_expression_should_take_an_argument); } else { const argument = allowInAnd(parseExpression); - if (isStringOrNumericLiteralLike(argument)) { - argument.text = internIdentifier(argument.text); + if (isAstStringOrNumericLiteralLike(argument)) { + argument.data.text = internIdentifier(argument.data.text); } argumentExpression = argument; } @@ -6382,9 +5531,9 @@ namespace Parser { return finishNode(indexedAccess, pos); } - function parseMemberExpressionRest(pos: number, expression: LeftHandSideExpression, allowOptionalChain: boolean): MemberExpression { + function parseMemberExpressionRest(pos: number, expression: AstLeftHandSideExpression, allowOptionalChain: boolean): AstMemberExpression { while (true) { - let questionDotToken: QuestionDotToken | undefined; + let questionDotToken: AstQuestionDotToken | undefined; let isPropertyAccess = false; if (allowOptionalChain && isStartOfOptionalPropertyOrElementAccessChain()) { questionDotToken = parseExpectedToken(SyntaxKind.QuestionDotToken); @@ -6407,8 +5556,8 @@ namespace Parser { if (isTemplateStartOfTaggedTemplate()) { // Absorb type arguments into TemplateExpression when preceding expression is ExpressionWithTypeArguments - expression = !questionDotToken && expression.kind === SyntaxKind.ExpressionWithTypeArguments ? - parseTaggedTemplateRest(pos, (expression as ExpressionWithTypeArguments).expression, questionDotToken, (expression as ExpressionWithTypeArguments).typeArguments) : + expression = !questionDotToken && isAstExpressionWithTypeArguments(expression) ? + parseTaggedTemplateRest(pos, expression.data.expression, questionDotToken, expression.data.typeArguments) : parseTaggedTemplateRest(pos, expression, questionDotToken, /*typeArguments*/ undefined); continue; } @@ -6426,7 +5575,7 @@ namespace Parser { } } - return expression as MemberExpression; + return expression as AstMemberExpression; } } @@ -6434,25 +5583,25 @@ namespace Parser { return token() === SyntaxKind.NoSubstitutionTemplateLiteral || token() === SyntaxKind.TemplateHead; } - function parseTaggedTemplateRest(pos: number, tag: LeftHandSideExpression, questionDotToken: QuestionDotToken | undefined, typeArguments: NodeArray | undefined) { + function parseTaggedTemplateRest(pos: number, tag: AstLeftHandSideExpression, questionDotToken: AstQuestionDotToken | undefined, typeArguments: AstNodeArray | undefined) { const tagExpression = factory.createTaggedTemplateExpression( tag, typeArguments, token() === SyntaxKind.NoSubstitutionTemplateLiteral ? - (reScanTemplateToken(/*isTaggedTemplate*/ true), parseLiteralNode() as NoSubstitutionTemplateLiteral) : + (reScanTemplateToken(/*isTaggedTemplate*/ true), parseLiteralNode() as AstNoSubstitutionTemplateLiteral) : parseTemplateExpression(/*isTaggedTemplate*/ true), ); if (questionDotToken || tag.flags & NodeFlags.OptionalChain) { - (tagExpression as Mutable).flags |= NodeFlags.OptionalChain; + tagExpression.flags |= NodeFlags.OptionalChain; } - tagExpression.questionDotToken = questionDotToken; + tagExpression.data.questionDotToken = questionDotToken; return finishNode(tagExpression, pos); } - function parseCallExpressionRest(pos: number, expression: LeftHandSideExpression): LeftHandSideExpression { + function parseCallExpressionRest(pos: number, expression: AstLeftHandSideExpression): AstLeftHandSideExpression { while (true) { expression = parseMemberExpressionRest(pos, expression, /*allowOptionalChain*/ true); - let typeArguments: NodeArray | undefined; + let typeArguments: AstNodeArray | undefined; const questionDotToken = parseOptionalToken(SyntaxKind.QuestionDotToken); if (questionDotToken) { typeArguments = tryParse(parseTypeArgumentsInExpression); @@ -6463,9 +5612,9 @@ namespace Parser { } if (typeArguments || token() === SyntaxKind.OpenParenToken) { // Absorb type arguments into CallExpression when preceding expression is ExpressionWithTypeArguments - if (!questionDotToken && expression.kind === SyntaxKind.ExpressionWithTypeArguments) { - typeArguments = (expression as ExpressionWithTypeArguments).typeArguments; - expression = (expression as ExpressionWithTypeArguments).expression; + if (!questionDotToken && isAstExpressionWithTypeArguments(expression)) { + typeArguments = expression.data.typeArguments; + expression = expression.data.expression; } const argumentList = parseArgumentList(); const callExpr = questionDotToken || tryReparseOptionalChain(expression) ? @@ -6476,7 +5625,7 @@ namespace Parser { } if (questionDotToken) { // We parsed `?.` but then failed to parse anything, so report a missing identifier here. - const name = createMissingNode(SyntaxKind.Identifier, /*reportAtCurrentPosition*/ false, Diagnostics.Identifier_expected); + const name = createMissingNode(SyntaxKind.Identifier, /*reportAtCurrentPosition*/ false, Diagnostics.Identifier_expected); expression = finishNode(factoryCreatePropertyAccessChain(expression, questionDotToken, name), pos); } break; @@ -6537,7 +5686,7 @@ namespace Parser { return scanner.hasPrecedingLineBreak() || isBinaryOperator() || !isStartOfExpression(); } - function parsePrimaryExpression(): PrimaryExpression { + function parsePrimaryExpression(): AstPrimaryExpression { switch (token()) { case SyntaxKind.NoSubstitutionTemplateLiteral: if (scanner.getTokenFlags() & TokenFlags.IsInvalid) { @@ -6553,7 +5702,7 @@ namespace Parser { case SyntaxKind.NullKeyword: case SyntaxKind.TrueKeyword: case SyntaxKind.FalseKeyword: - return parseTokenNode(); + return parseTokenNode(); case SyntaxKind.OpenParenToken: return parseParenthesizedExpression(); case SyntaxKind.OpenBracketToken: @@ -6592,7 +5741,7 @@ namespace Parser { return parseIdentifier(Diagnostics.Expression_expected); } - function parseParenthesizedExpression(): ParenthesizedExpression { + function parseParenthesizedExpression(): AstParenthesizedExpression { const pos = getNodePos(); const hasJSDoc = hasPrecedingJSDocComment(); parseExpected(SyntaxKind.OpenParenToken); @@ -6601,24 +5750,24 @@ namespace Parser { return withJSDoc(finishNode(factoryCreateParenthesizedExpression(expression), pos), hasJSDoc); } - function parseSpreadElement(): Expression { + function parseSpreadElement(): AstExpression { const pos = getNodePos(); parseExpected(SyntaxKind.DotDotDotToken); const expression = parseAssignmentExpressionOrHigher(/*allowReturnTypeInArrowFunction*/ true); return finishNode(factory.createSpreadElement(expression), pos); } - function parseArgumentOrArrayLiteralElement(): Expression { + function parseArgumentOrArrayLiteralElement(): AstExpression { return token() === SyntaxKind.DotDotDotToken ? parseSpreadElement() : token() === SyntaxKind.CommaToken ? finishNode(factory.createOmittedExpression(), getNodePos()) : parseAssignmentExpressionOrHigher(/*allowReturnTypeInArrowFunction*/ true); } - function parseArgumentExpression(): Expression { + function parseArgumentExpression(): AstExpression { return doOutsideOfContext(disallowInAndDecoratorContext, parseArgumentOrArrayLiteralElement); } - function parseArrayLiteralExpression(): ArrayLiteralExpression { + function parseArrayLiteralExpression(): AstArrayLiteralExpression { const pos = getNodePos(); const openBracketPosition = scanner.getTokenStart(); const openBracketParsed = parseExpected(SyntaxKind.OpenBracketToken); @@ -6628,7 +5777,7 @@ namespace Parser { return finishNode(factoryCreateArrayLiteralExpression(elements, multiLine), pos); } - function parseObjectLiteralElement(): ObjectLiteralElementLike { + function parseObjectLiteralElement(): AstObjectLiteralElementLike { const pos = getNodePos(); const hasJSDoc = hasPrecedingJSDocComment(); @@ -6662,15 +5811,15 @@ namespace Parser { // CoverInitializedName[Yield] : // IdentifierReference[?Yield] Initializer[In, ?Yield] // this is necessary because ObjectLiteral productions are also used to cover grammar for ObjectAssignmentPattern - let node: Mutable; + let node: AstShorthandPropertyAssignment | AstPropertyAssignment; const isShorthandPropertyAssignment = tokenIsIdentifier && (token() !== SyntaxKind.ColonToken); if (isShorthandPropertyAssignment) { const equalsToken = parseOptionalToken(SyntaxKind.EqualsToken); const objectAssignmentInitializer = equalsToken ? allowInAnd(() => parseAssignmentExpressionOrHigher(/*allowReturnTypeInArrowFunction*/ true)) : undefined; - node = factory.createShorthandPropertyAssignment(name as Identifier, objectAssignmentInitializer); + node = factory.createShorthandPropertyAssignment(name as AstIdentifier, objectAssignmentInitializer); // Save equals token for error reporting. // TODO(rbuckton): Consider manufacturing this when we need to report an error as it is otherwise not useful. - node.equalsToken = equalsToken; + node.data.equalsToken = equalsToken; } else { parseExpected(SyntaxKind.ColonToken); @@ -6678,13 +5827,13 @@ namespace Parser { node = factory.createPropertyAssignment(name, initializer); } // Decorators, Modifiers, questionToken, and exclamationToken are not supported by property assignments and are reported in the grammar checker - node.modifiers = modifiers; - node.questionToken = questionToken; - node.exclamationToken = exclamationToken; + node.data.modifiers = modifiers; + node.data.questionToken = questionToken; + node.data.exclamationToken = exclamationToken; return withJSDoc(finishNode(node, pos), hasJSDoc); } - function parseObjectLiteralExpression(): ObjectLiteralExpression { + function parseObjectLiteralExpression(): AstObjectLiteralExpression { const pos = getNodePos(); const openBracePosition = scanner.getTokenStart(); const openBraceParsed = parseExpected(SyntaxKind.OpenBraceToken); @@ -6694,7 +5843,7 @@ namespace Parser { return finishNode(factoryCreateObjectLiteralExpression(properties, multiLine), pos); } - function parseFunctionExpression(): FunctionExpression { + function parseFunctionExpression(): AstFunctionExpression { // GeneratorExpression: // function* BindingIdentifier [Yield][opt](FormalParameters[Yield]){ GeneratorBody } // @@ -6709,7 +5858,7 @@ namespace Parser { parseExpected(SyntaxKind.FunctionKeyword); const asteriskToken = parseOptionalToken(SyntaxKind.AsteriskToken); const isGenerator = asteriskToken ? SignatureFlags.Yield : SignatureFlags.None; - const isAsync = some(modifiers, isAsyncModifier) ? SignatureFlags.Await : SignatureFlags.None; + const isAsync = some(modifiers?.items, isAstAsyncModifier) ? SignatureFlags.Await : SignatureFlags.None; const name = isGenerator && isAsync ? doInYieldAndAwaitContext(parseOptionalBindingIdentifier) : isGenerator ? doInYieldContext(parseOptionalBindingIdentifier) : isAsync ? doInAwaitContext(parseOptionalBindingIdentifier) : @@ -6726,11 +5875,11 @@ namespace Parser { return withJSDoc(finishNode(node, pos), hasJSDoc); } - function parseOptionalBindingIdentifier(): Identifier | undefined { + function parseOptionalBindingIdentifier(): AstIdentifier | undefined { return isBindingIdentifier() ? parseBindingIdentifier() : undefined; } - function parseNewExpressionOrNewDotTarget(): NewExpression | MetaProperty { + function parseNewExpressionOrNewDotTarget(): AstNewExpression | AstMetaProperty { const pos = getNodePos(); parseExpected(SyntaxKind.NewKeyword); if (parseOptional(SyntaxKind.DotToken)) { @@ -6738,12 +5887,12 @@ namespace Parser { return finishNode(factory.createMetaProperty(SyntaxKind.NewKeyword, name), pos); } const expressionPos = getNodePos(); - let expression: LeftHandSideExpression = parseMemberExpressionRest(expressionPos, parsePrimaryExpression(), /*allowOptionalChain*/ false); - let typeArguments: NodeArray | undefined; + let expression: AstLeftHandSideExpression = parseMemberExpressionRest(expressionPos, parsePrimaryExpression(), /*allowOptionalChain*/ false); + let typeArguments: AstNodeArray | undefined; // Absorb type arguments into NewExpression when preceding expression is ExpressionWithTypeArguments - if (expression.kind === SyntaxKind.ExpressionWithTypeArguments) { - typeArguments = (expression as ExpressionWithTypeArguments).typeArguments; - expression = (expression as ExpressionWithTypeArguments).expression; + if (isAstExpressionWithTypeArguments(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)); @@ -6753,7 +5902,7 @@ namespace Parser { } // STATEMENTS - function parseBlock(ignoreMissingOpenBrace: boolean, diagnosticMessage?: DiagnosticMessage): Block { + function parseBlock(ignoreMissingOpenBrace: boolean, diagnosticMessage?: DiagnosticMessage): AstBlock { const pos = getNodePos(); const hasJSDoc = hasPrecedingJSDocComment(); const openBracePosition = scanner.getTokenStart(); @@ -6771,12 +5920,12 @@ namespace Parser { return result; } else { - const statements = createMissingList(); + const statements = createMissingList(); return withJSDoc(finishNode(factoryCreateBlock(statements, /*multiLine*/ undefined), pos), hasJSDoc); } } - function parseFunctionBlock(flags: SignatureFlags, diagnosticMessage?: DiagnosticMessage): Block { + function parseFunctionBlock(flags: SignatureFlags, diagnosticMessage?: DiagnosticMessage): AstBlock { const savedYieldContext = inYieldContext(); setYieldContext(!!(flags & SignatureFlags.Yield)); @@ -6806,14 +5955,14 @@ namespace Parser { return block; } - function parseEmptyStatement(): Statement { + function parseEmptyStatement(): AstStatement { const pos = getNodePos(); const hasJSDoc = hasPrecedingJSDocComment(); parseExpected(SyntaxKind.SemicolonToken); return withJSDoc(finishNode(factory.createEmptyStatement(), pos), hasJSDoc); } - function parseIfStatement(): IfStatement { + function parseIfStatement(): AstIfStatement { const pos = getNodePos(); const hasJSDoc = hasPrecedingJSDocComment(); parseExpected(SyntaxKind.IfKeyword); @@ -6826,7 +5975,7 @@ namespace Parser { return withJSDoc(finishNode(factoryCreateIfStatement(expression, thenStatement, elseStatement), pos), hasJSDoc); } - function parseDoStatement(): DoStatement { + function parseDoStatement(): AstDoStatement { const pos = getNodePos(); const hasJSDoc = hasPrecedingJSDocComment(); parseExpected(SyntaxKind.DoKeyword); @@ -6845,7 +5994,7 @@ namespace Parser { return withJSDoc(finishNode(factory.createDoStatement(statement, expression), pos), hasJSDoc); } - function parseWhileStatement(): WhileStatement { + function parseWhileStatement(): AstWhileStatement { const pos = getNodePos(); const hasJSDoc = hasPrecedingJSDocComment(); parseExpected(SyntaxKind.WhileKeyword); @@ -6857,14 +6006,14 @@ namespace Parser { return withJSDoc(finishNode(factoryCreateWhileStatement(expression, statement), pos), hasJSDoc); } - function parseForOrForInOrForOfStatement(): Statement { + function parseForOrForInOrForOfStatement(): AstStatement { const pos = getNodePos(); const hasJSDoc = hasPrecedingJSDocComment(); parseExpected(SyntaxKind.ForKeyword); const awaitToken = parseOptionalToken(SyntaxKind.AwaitKeyword); parseExpected(SyntaxKind.OpenParenToken); - let initializer!: VariableDeclarationList | Expression; + let initializer!: AstForInitializer; if (token() !== SyntaxKind.SemicolonToken) { if ( token() === SyntaxKind.VarKeyword || token() === SyntaxKind.LetKeyword || token() === SyntaxKind.ConstKeyword || @@ -6879,7 +6028,7 @@ namespace Parser { } } - let node: IterationStatement; + let node: AstIterationStatement; if (awaitToken ? parseExpected(SyntaxKind.OfKeyword) : parseOptional(SyntaxKind.OfKeyword)) { const expression = allowInAnd(() => parseAssignmentExpressionOrHigher(/*allowReturnTypeInArrowFunction*/ true)); parseExpected(SyntaxKind.CloseParenToken); @@ -6903,10 +6052,10 @@ namespace Parser { node = factoryCreateForStatement(initializer, condition, incrementor, parseStatement()); } - return withJSDoc(finishNode(node, pos) as ForStatement | ForInOrOfStatement, hasJSDoc); + return withJSDoc(finishNode(node, pos) as AstForStatement | AstForInOrOfStatement, hasJSDoc); } - function parseBreakOrContinueStatement(kind: SyntaxKind): BreakOrContinueStatement { + function parseBreakOrContinueStatement(kind: SyntaxKind): AstBreakOrContinueStatement { const pos = getNodePos(); const hasJSDoc = hasPrecedingJSDocComment(); @@ -6920,7 +6069,7 @@ namespace Parser { return withJSDoc(finishNode(node, pos), hasJSDoc); } - function parseReturnStatement(): ReturnStatement { + function parseReturnStatement(): AstReturnStatement { const pos = getNodePos(); const hasJSDoc = hasPrecedingJSDocComment(); parseExpected(SyntaxKind.ReturnKeyword); @@ -6929,7 +6078,7 @@ namespace Parser { return withJSDoc(finishNode(factory.createReturnStatement(expression), pos), hasJSDoc); } - function parseWithStatement(): WithStatement { + function parseWithStatement(): AstWithStatement { const pos = getNodePos(); const hasJSDoc = hasPrecedingJSDocComment(); parseExpected(SyntaxKind.WithKeyword); @@ -6941,7 +6090,7 @@ namespace Parser { return withJSDoc(finishNode(factory.createWithStatement(expression, statement), pos), hasJSDoc); } - function parseCaseClause(): CaseClause { + function parseCaseClause(): AstCaseClause { const pos = getNodePos(); const hasJSDoc = hasPrecedingJSDocComment(); parseExpected(SyntaxKind.CaseKeyword); @@ -6951,7 +6100,7 @@ namespace Parser { return withJSDoc(finishNode(factory.createCaseClause(expression, statements), pos), hasJSDoc); } - function parseDefaultClause(): DefaultClause { + function parseDefaultClause(): AstDefaultClause { const pos = getNodePos(); parseExpected(SyntaxKind.DefaultKeyword); parseExpected(SyntaxKind.ColonToken); @@ -6959,11 +6108,11 @@ namespace Parser { return finishNode(factory.createDefaultClause(statements), pos); } - function parseCaseOrDefaultClause(): CaseOrDefaultClause { + function parseCaseOrDefaultClause(): AstCaseOrDefaultClause { return token() === SyntaxKind.CaseKeyword ? parseCaseClause() : parseDefaultClause(); } - function parseCaseBlock(): CaseBlock { + function parseCaseBlock(): AstCaseBlock { const pos = getNodePos(); parseExpected(SyntaxKind.OpenBraceToken); const clauses = parseList(ParsingContext.SwitchClauses, parseCaseOrDefaultClause); @@ -6971,7 +6120,7 @@ namespace Parser { return finishNode(factory.createCaseBlock(clauses), pos); } - function parseSwitchStatement(): SwitchStatement { + function parseSwitchStatement(): AstSwitchStatement { const pos = getNodePos(); const hasJSDoc = hasPrecedingJSDocComment(); parseExpected(SyntaxKind.SwitchKeyword); @@ -6982,7 +6131,7 @@ namespace Parser { return withJSDoc(finishNode(factory.createSwitchStatement(expression, caseBlock), pos), hasJSDoc); } - function parseThrowStatement(): ThrowStatement { + function parseThrowStatement(): AstThrowStatement { // ThrowStatement[Yield] : // throw [no LineTerminator here]Expression[In, ?Yield]; @@ -7007,7 +6156,7 @@ namespace Parser { } // TODO: Review for error recovery - function parseTryStatement(): TryStatement { + function parseTryStatement(): AstTryStatement { const pos = getNodePos(); const hasJSDoc = hasPrecedingJSDocComment(); @@ -7017,7 +6166,7 @@ namespace Parser { // If we don't have a catch clause, then we must have a finally clause. Try to parse // one out no matter what. - let finallyBlock: Block | undefined; + let finallyBlock: AstBlock | undefined; if (!catchClause || token() === SyntaxKind.FinallyKeyword) { parseExpected(SyntaxKind.FinallyKeyword, Diagnostics.catch_or_finally_expected); finallyBlock = parseBlock(/*ignoreMissingOpenBrace*/ false); @@ -7026,7 +6175,7 @@ namespace Parser { return withJSDoc(finishNode(factory.createTryStatement(tryBlock, catchClause, finallyBlock), pos), hasJSDoc); } - function parseCatchClause(): CatchClause { + function parseCatchClause(): AstCatchClause { const pos = getNodePos(); parseExpected(SyntaxKind.CatchKeyword); @@ -7044,7 +6193,7 @@ namespace Parser { return finishNode(factory.createCatchClause(variableDeclaration, block), pos); } - function parseDebuggerStatement(): Statement { + function parseDebuggerStatement(): AstStatement { const pos = getNodePos(); const hasJSDoc = hasPrecedingJSDocComment(); parseExpected(SyntaxKind.DebuggerKeyword); @@ -7052,16 +6201,16 @@ namespace Parser { return withJSDoc(finishNode(factory.createDebuggerStatement(), pos), hasJSDoc); } - function parseExpressionOrLabeledStatement(): ExpressionStatement | LabeledStatement { + function parseExpressionOrLabeledStatement(): AstExpressionStatement | AstLabeledStatement { // Avoiding having to do the lookahead for a labeled statement by just trying to parse // out an expression, seeing if it is identifier and then seeing if it is followed by // a colon. const pos = getNodePos(); let hasJSDoc = hasPrecedingJSDocComment(); - let node: ExpressionStatement | LabeledStatement; + let node: AstExpressionStatement | AstLabeledStatement; const hasParen = token() === SyntaxKind.OpenParenToken; const expression = allowInAnd(parseExpression); - if (isIdentifierNode(expression) && parseOptional(SyntaxKind.ColonToken)) { + if (isAstIdentifier(expression) && parseOptional(SyntaxKind.ColonToken)) { node = factory.createLabeledStatement(expression, parseStatement()); } else { @@ -7300,7 +6449,7 @@ namespace Parser { return lookAhead(nextTokenIsUsingKeywordThenBindingIdentifierOrStartOfObjectDestructuringOnSameLine); } - function parseStatement(): Statement { + function parseStatement(): AstStatement { switch (token()) { case SyntaxKind.SemicolonToken: return parseEmptyStatement(); @@ -7383,26 +6532,22 @@ namespace Parser { return parseExpressionOrLabeledStatement(); } - function isDeclareModifier(modifier: ModifierLike) { - return modifier.kind === SyntaxKind.DeclareKeyword; - } - - function parseDeclaration(): Statement { + function parseDeclaration(): AstStatement { // `parseListElement` attempted to get the reused node at this position, // but the ambient context flag was not yet set, so the node appeared // not reusable in that context. const pos = getNodePos(); const hasJSDoc = hasPrecedingJSDocComment(); const modifiers = parseModifiers(/*allowDecorators*/ true); - const isAmbient = some(modifiers, isDeclareModifier); + const isAmbient = some(modifiers?.items, isAstDeclareKeyword); if (isAmbient) { const node = tryReuseAmbientDeclaration(pos); if (node) { return node; } - for (const m of modifiers!) { - (m as Mutable).flags |= NodeFlags.Ambient; + for (const m of modifiers!.items) { + m.flags |= NodeFlags.Ambient; } return doInsideOfContext(NodeFlags.Ambient, () => parseDeclarationWorker(pos, hasJSDoc, modifiers)); } @@ -7411,18 +6556,18 @@ namespace Parser { } } - function tryReuseAmbientDeclaration(pos: number): Statement | undefined { + function tryReuseAmbientDeclaration(pos: number): AstStatement | undefined { return doInsideOfContext(NodeFlags.Ambient, () => { // TODO(jakebailey): this is totally wrong; `parsingContext` is the result of ORing a bunch of `1 << ParsingContext.XYZ`. // The enum should really be a bunch of flags. const node = currentNode(parsingContext, pos); if (node) { - return consumeNode(node) as Statement; + return consumeNode(node) as AstStatement; } }); } - function parseDeclarationWorker(pos: number, hasJSDoc: boolean, modifiersIn: NodeArray | undefined): Statement { + function parseDeclarationWorker(pos: number, hasJSDoc: boolean, modifiersIn: AstNodeArray | undefined): AstStatement { switch (token()) { case SyntaxKind.VarKeyword: case SyntaxKind.LetKeyword: @@ -7461,9 +6606,9 @@ namespace Parser { if (modifiersIn) { // We reached this point because we encountered decorators and/or modifiers and assumed a declaration // would follow. For recovery and error reporting purposes, return an incomplete declaration. - const missing = createMissingNode(SyntaxKind.MissingDeclaration, /*reportAtCurrentPosition*/ true, Diagnostics.Declaration_expected); + const missing = createMissingNode(SyntaxKind.MissingDeclaration, /*reportAtCurrentPosition*/ true, Diagnostics.Declaration_expected); setTextRangePos(missing, pos); - (missing as Mutable).modifiers = modifiersIn; + missing.data.modifiers = modifiersIn; return missing; } return undefined!; // TODO: GH#18217 @@ -7484,7 +6629,7 @@ namespace Parser { return !scanner.hasPrecedingLineBreak() && (isIdentifier() || token() === SyntaxKind.StringLiteral); } - function parseFunctionBlockOrSemicolon(flags: SignatureFlags, diagnosticMessage?: DiagnosticMessage): Block | undefined { + function parseFunctionBlockOrSemicolon(flags: SignatureFlags, diagnosticMessage?: DiagnosticMessage): AstBlock | undefined { if (token() !== SyntaxKind.OpenBraceToken) { if (flags & SignatureFlags.Type) { parseTypeMemberSemicolon(); @@ -7500,7 +6645,7 @@ namespace Parser { // DECLARATIONS - function parseArrayBindingElement(): ArrayBindingElement { + function parseArrayBindingElement(): AstArrayBindingElement { const pos = getNodePos(); if (token() === SyntaxKind.CommaToken) { return finishNode(factory.createOmittedExpression(), pos); @@ -7511,14 +6656,14 @@ namespace Parser { return finishNode(factory.createBindingElement(dotDotDotToken, /*propertyName*/ undefined, name, initializer), pos); } - function parseObjectBindingElement(): BindingElement { + function parseObjectBindingElement(): AstBindingElement { const pos = getNodePos(); const dotDotDotToken = parseOptionalToken(SyntaxKind.DotDotDotToken); const tokenIsIdentifier = isBindingIdentifier(); - let propertyName: PropertyName | undefined = parsePropertyName(); - let name: BindingName; + let propertyName: AstPropertyName | undefined = parsePropertyName(); + let name: AstBindingName; if (tokenIsIdentifier && token() !== SyntaxKind.ColonToken) { - name = propertyName as Identifier; + name = propertyName as AstIdentifier; propertyName = undefined; } else { @@ -7529,7 +6674,7 @@ namespace Parser { return finishNode(factory.createBindingElement(dotDotDotToken, propertyName, name, initializer), pos); } - function parseObjectBindingPattern(): ObjectBindingPattern { + function parseObjectBindingPattern(): AstObjectBindingPattern { const pos = getNodePos(); parseExpected(SyntaxKind.OpenBraceToken); const elements = allowInAnd(() => parseDelimitedList(ParsingContext.ObjectBindingElements, parseObjectBindingElement)); @@ -7537,7 +6682,7 @@ namespace Parser { return finishNode(factory.createObjectBindingPattern(elements), pos); } - function parseArrayBindingPattern(): ArrayBindingPattern { + function parseArrayBindingPattern(): AstArrayBindingPattern { const pos = getNodePos(); parseExpected(SyntaxKind.OpenBracketToken); const elements = allowInAnd(() => parseDelimitedList(ParsingContext.ArrayBindingElements, parseArrayBindingElement)); @@ -7552,7 +6697,7 @@ namespace Parser { || isBindingIdentifier(); } - function parseIdentifierOrPattern(privateIdentifierDiagnosticMessage?: DiagnosticMessage): Identifier | BindingPattern { + function parseIdentifierOrPattern(privateIdentifierDiagnosticMessage?: DiagnosticMessage): AstIdentifier | AstBindingPattern { if (token() === SyntaxKind.OpenBracketToken) { return parseArrayBindingPattern(); } @@ -7566,16 +6711,16 @@ namespace Parser { return parseVariableDeclaration(/*allowExclamation*/ true); } - function parseVariableDeclaration(allowExclamation?: boolean): VariableDeclaration { + function parseVariableDeclaration(allowExclamation?: boolean): AstVariableDeclaration { const pos = getNodePos(); const hasJSDoc = hasPrecedingJSDocComment(); const name = parseIdentifierOrPattern(Diagnostics.Private_identifiers_are_not_allowed_in_variable_declarations); - let exclamationToken: ExclamationToken | undefined; + let exclamationToken: AstExclamationToken | undefined; if ( allowExclamation && name.kind === SyntaxKind.Identifier && token() === SyntaxKind.ExclamationToken && !scanner.hasPrecedingLineBreak() ) { - exclamationToken = parseTokenNode>(); + exclamationToken = parseTokenNode(); } const type = parseTypeAnnotation(); const initializer = isInOrOfKeyword(token()) ? undefined : parseInitializer(); @@ -7583,7 +6728,7 @@ namespace Parser { return withJSDoc(finishNode(node, pos), hasJSDoc); } - function parseVariableDeclarationList(inForStatementInitializer: boolean): VariableDeclarationList { + function parseVariableDeclarationList(inForStatementInitializer: boolean): AstVariableDeclarationList { const pos = getNodePos(); let flags: NodeFlags = 0; @@ -7619,9 +6764,9 @@ namespace Parser { // So we need to look ahead to determine if 'of' should be treated as a keyword in // this context. // The checker will then give an error that there is an empty declaration list. - let declarations: readonly VariableDeclaration[]; + let declarations: AstNodeArray; if (token() === SyntaxKind.OfKeyword && lookAhead(canFollowContextualOfKeyword)) { - declarations = createMissingList(); + declarations = createMissingList(); } else { const savedDisallowIn = inDisallowInContext(); @@ -7642,16 +6787,16 @@ namespace Parser { return nextTokenIsIdentifier() && nextToken() === SyntaxKind.CloseParenToken; } - function parseVariableStatement(pos: number, hasJSDoc: boolean, modifiers: NodeArray | undefined): VariableStatement { + function parseVariableStatement(pos: number, hasJSDoc: boolean, modifiers: AstNodeArray | undefined): AstVariableStatement { const declarationList = parseVariableDeclarationList(/*inForStatementInitializer*/ false); parseSemicolon(); const node = factoryCreateVariableStatement(modifiers, declarationList); return withJSDoc(finishNode(node, pos), hasJSDoc); } - function parseFunctionDeclaration(pos: number, hasJSDoc: boolean, modifiers: NodeArray | undefined): FunctionDeclaration { + function parseFunctionDeclaration(pos: number, hasJSDoc: boolean, modifiers: AstNodeArray | undefined): AstFunctionDeclaration { const savedAwaitContext = inAwaitContext(); - const modifierFlags = modifiersToFlags(modifiers); + const modifierFlags = modifiersToFlags(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. @@ -7675,12 +6820,12 @@ namespace Parser { if (token() === SyntaxKind.StringLiteral && lookAhead(nextToken) === SyntaxKind.OpenParenToken) { return tryParse(() => { const literalNode = parseLiteralNode(); - return literalNode.text === "constructor" ? literalNode : undefined; + return literalNode.data.text === "constructor" ? literalNode : undefined; }); } } - function tryParseConstructorDeclaration(pos: number, hasJSDoc: boolean, modifiers: NodeArray | undefined): ConstructorDeclaration | undefined { + function tryParseConstructorDeclaration(pos: number, hasJSDoc: boolean, modifiers: AstNodeArray | undefined): AstConstructorDeclaration | undefined { return tryParse(() => { if (parseConstructorName()) { const typeParameters = parseTypeParameters(); @@ -7690,8 +6835,8 @@ namespace Parser { const node = factory.createConstructorDeclaration(modifiers, parameters, body); // Attach invalid nodes if they exist so that we can report them in the grammar checker. - (node as Mutable).typeParameters = typeParameters; - (node as Mutable).type = type; + node.data.typeParameters = typeParameters; + node.data.type = type; return withJSDoc(finishNode(node, pos), hasJSDoc); } }); @@ -7700,15 +6845,15 @@ namespace Parser { function parseMethodDeclaration( pos: number, hasJSDoc: boolean, - modifiers: NodeArray | undefined, - asteriskToken: AsteriskToken | undefined, - name: PropertyName, - questionToken: QuestionToken | undefined, - exclamationToken: ExclamationToken | undefined, + modifiers: AstNodeArray | undefined, + asteriskToken: AstAsteriskToken | undefined, + name: AstPropertyName, + questionToken: AstQuestionToken | undefined, + exclamationToken: AstExclamationToken | undefined, diagnosticMessage?: DiagnosticMessage, - ): MethodDeclaration { + ): AstMethodDeclaration { const isGenerator = asteriskToken ? SignatureFlags.Yield : SignatureFlags.None; - const isAsync = some(modifiers, isAsyncModifier) ? SignatureFlags.Await : SignatureFlags.None; + const isAsync = some(modifiers?.items, isAstAsyncModifier) ? SignatureFlags.Await : SignatureFlags.None; const typeParameters = parseTypeParameters(); const parameters = parseParameters(isGenerator | isAsync); const type = parseReturnType(SyntaxKind.ColonToken, /*isType*/ false); @@ -7725,17 +6870,17 @@ namespace Parser { ); // An exclamation token on a method is invalid syntax and will be handled by the grammar checker - (node as Mutable).exclamationToken = exclamationToken; + node.data.exclamationToken = exclamationToken; return withJSDoc(finishNode(node, pos), hasJSDoc); } function parsePropertyDeclaration( pos: number, hasJSDoc: boolean, - modifiers: NodeArray | undefined, - name: PropertyName, - questionToken: QuestionToken | undefined, - ): PropertyDeclaration { + modifiers: AstNodeArray | undefined, + name: AstPropertyName, + questionToken: AstQuestionToken | undefined, + ): AstPropertyDeclaration { const exclamationToken = !questionToken && !scanner.hasPrecedingLineBreak() ? parseOptionalToken(SyntaxKind.ExclamationToken) : undefined; const type = parseTypeAnnotation(); const initializer = doOutsideOfContext(NodeFlags.YieldContext | NodeFlags.AwaitContext | NodeFlags.DisallowInContext, parseInitializer); @@ -7753,8 +6898,8 @@ namespace Parser { function parsePropertyOrMethodDeclaration( pos: number, hasJSDoc: boolean, - modifiers: NodeArray | undefined, - ): PropertyDeclaration | MethodDeclaration { + modifiers: AstNodeArray | undefined, + ): AstPropertyDeclaration | AstMethodDeclaration { const asteriskToken = parseOptionalToken(SyntaxKind.AsteriskToken); const name = parsePropertyName(); // Note: this is not legal as per the grammar. But we allow it in the parser and @@ -7766,7 +6911,7 @@ namespace Parser { return parsePropertyDeclaration(pos, hasJSDoc, modifiers, name, questionToken); } - function parseAccessorDeclaration(pos: number, hasJSDoc: boolean, modifiers: NodeArray | undefined, kind: AccessorDeclaration["kind"], flags: SignatureFlags): AccessorDeclaration { + function parseAccessorDeclaration(pos: number, hasJSDoc: boolean, modifiers: AstNodeArray | undefined, kind: AstAccessorDeclaration["kind"], flags: SignatureFlags): AstAccessorDeclaration { const name = parsePropertyName(); const typeParameters = parseTypeParameters(); const parameters = parseParameters(SignatureFlags.None); @@ -7776,8 +6921,10 @@ namespace Parser { ? factory.createGetAccessorDeclaration(modifiers, name, parameters, type, body) : 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 as Mutable).typeParameters = typeParameters; - if (isSetAccessorDeclaration(node)) (node as Mutable).type = type; + node.data.typeParameters = typeParameters; + if (isAstSetAccessorDeclaration(node)) { + node.data.type = type; + } return withJSDoc(finishNode(node, pos), hasJSDoc); } @@ -7850,11 +6997,11 @@ namespace Parser { return false; } - function parseClassStaticBlockDeclaration(pos: number, hasJSDoc: boolean, modifiers: NodeArray | undefined): ClassStaticBlockDeclaration { + function parseClassStaticBlockDeclaration(pos: number, hasJSDoc: boolean, modifiers: AstNodeArray | undefined): AstClassStaticBlockDeclaration { parseExpectedToken(SyntaxKind.StaticKeyword); const body = parseClassStaticBlockBody(); const node = withJSDoc(finishNode(factory.createClassStaticBlockDeclaration(body), pos), hasJSDoc); - (node as Mutable).modifiers = modifiers; + node.data.modifiers = modifiers; return node; } @@ -7886,7 +7033,7 @@ namespace Parser { return parseLeftHandSideExpressionOrHigher(); } - function tryParseDecorator(): Decorator | undefined { + function tryParseDecorator(): AstDecorator | undefined { const pos = getNodePos(); if (!parseOptional(SyntaxKind.AtToken)) { return undefined; @@ -7895,7 +7042,7 @@ namespace Parser { return finishNode(factory.createDecorator(expression), pos); } - function tryParseModifier(hasSeenStaticModifier: boolean, permitConstAsModifier?: boolean, stopOnStartOfClassStaticBlock?: boolean): Modifier | undefined { + function tryParseModifier(hasSeenStaticModifier: boolean, permitConstAsModifier?: boolean, stopOnStartOfClassStaticBlock?: boolean): AstModifier | undefined { const pos = getNodePos(); const kind = token(); @@ -7918,7 +7065,7 @@ namespace Parser { } } - return finishNode(factoryCreateToken(kind as Modifier["kind"]), pos); + return finishNode(factoryCreateToken(kind as AstModifier["kind"]) as AstModifier, pos); } /* @@ -7928,11 +7075,11 @@ namespace Parser { * * In such situations, 'permitConstAsModifier' should be set to true. */ - function parseModifiers(allowDecorators: false, permitConstAsModifier?: boolean, stopOnStartOfClassStaticBlock?: boolean): NodeArray | undefined; - function parseModifiers(allowDecorators: true, permitConstAsModifier?: boolean, stopOnStartOfClassStaticBlock?: boolean): NodeArray | undefined; - function parseModifiers(allowDecorators: boolean, permitConstAsModifier?: boolean, stopOnStartOfClassStaticBlock?: boolean): NodeArray | undefined { + function parseModifiers(allowDecorators: false, permitConstAsModifier?: boolean, stopOnStartOfClassStaticBlock?: boolean): AstNodeArray | undefined; + function parseModifiers(allowDecorators: true, permitConstAsModifier?: boolean, stopOnStartOfClassStaticBlock?: boolean): AstNodeArray | undefined; + function parseModifiers(allowDecorators: boolean, permitConstAsModifier?: boolean, stopOnStartOfClassStaticBlock?: boolean): AstNodeArray | undefined { const pos = getNodePos(); - let list: ModifierLike[] | undefined; + let list: AstModifierLike[] | undefined; let decorator, modifier, hasSeenStaticModifier = false, hasLeadingModifier = false, hasTrailingDecorator = false; // Decorators should be contiguous in a list of modifiers but can potentially appear in two places (i.e., `[...leadingDecorators, ...leadingModifiers, ...trailingDecorators, ...trailingModifiers]`). @@ -7972,18 +7119,18 @@ namespace Parser { return list && createNodeArray(list, pos); } - function parseModifiersForArrowFunction(): NodeArray | undefined { - let modifiers: NodeArray | undefined; + function parseModifiersForArrowFunction(): AstNodeArray | undefined { + let modifiers: AstNodeArray | undefined; if (token() === SyntaxKind.AsyncKeyword) { const pos = getNodePos(); nextToken(); const modifier = finishNode(factoryCreateToken(SyntaxKind.AsyncKeyword), pos); - modifiers = createNodeArray([modifier], pos); + modifiers = createNodeArray([modifier], pos); } return modifiers; } - function parseClassElement(): ClassElement { + function parseClassElement(): AstClassElement { const pos = getNodePos(); const hasJSDoc = hasPrecedingJSDocComment(); if (token() === SyntaxKind.SemicolonToken) { @@ -8025,10 +7172,10 @@ namespace Parser { token() === SyntaxKind.AsteriskToken || token() === SyntaxKind.OpenBracketToken ) { - const isAmbient = some(modifiers, isDeclareModifier); + const isAmbient = some(modifiers?.items, isAstDeclareKeyword); if (isAmbient) { - for (const m of modifiers!) { - (m as Mutable).flags |= NodeFlags.Ambient; + for (const m of modifiers!.items) { + m.flags |= NodeFlags.Ambient; } return doInsideOfContext(NodeFlags.Ambient, () => parsePropertyOrMethodDeclaration(pos, hasJSDoc, modifiers)); } @@ -8039,7 +7186,7 @@ namespace Parser { if (modifiers) { // treat this as a property declaration with a missing name. - const name = createMissingNode(SyntaxKind.Identifier, /*reportAtCurrentPosition*/ true, Diagnostics.Declaration_expected); + const name = createMissingNode(SyntaxKind.Identifier, /*reportAtCurrentPosition*/ true, Diagnostics.Declaration_expected); return parsePropertyDeclaration(pos, hasJSDoc, modifiers, name, /*questionToken*/ undefined); } @@ -8047,36 +7194,36 @@ namespace Parser { return Debug.fail("Should not have attempted to parse class member declaration."); } - function parseDecoratedExpression(): PrimaryExpression { + function parseDecoratedExpression(): AstPrimaryExpression { const pos = getNodePos(); const hasJSDoc = hasPrecedingJSDocComment(); const modifiers = parseModifiers(/*allowDecorators*/ true); if (token() === SyntaxKind.ClassKeyword) { - return parseClassDeclarationOrExpression(pos, hasJSDoc, modifiers, SyntaxKind.ClassExpression) as ClassExpression; + return parseClassDeclarationOrExpression(pos, hasJSDoc, modifiers, SyntaxKind.ClassExpression) as AstClassExpression; } - const missing = createMissingNode(SyntaxKind.MissingDeclaration, /*reportAtCurrentPosition*/ true, Diagnostics.Expression_expected); + const missing = createMissingNode(SyntaxKind.MissingDeclaration, /*reportAtCurrentPosition*/ true, Diagnostics.Expression_expected); setTextRangePos(missing, pos); - (missing as Mutable).modifiers = modifiers; + missing.data.modifiers = modifiers; return missing; } - function parseClassExpression(): ClassExpression { - return parseClassDeclarationOrExpression(getNodePos(), hasPrecedingJSDocComment(), /*modifiers*/ undefined, SyntaxKind.ClassExpression) as ClassExpression; + function parseClassExpression(): AstClassExpression { + return parseClassDeclarationOrExpression(getNodePos(), hasPrecedingJSDocComment(), /*modifiers*/ undefined, SyntaxKind.ClassExpression) as AstClassExpression; } - function parseClassDeclaration(pos: number, hasJSDoc: boolean, modifiers: NodeArray | undefined): ClassDeclaration { - return parseClassDeclarationOrExpression(pos, hasJSDoc, modifiers, SyntaxKind.ClassDeclaration) as ClassDeclaration; + function parseClassDeclaration(pos: number, hasJSDoc: boolean, modifiers: AstNodeArray | undefined): AstClassDeclaration { + return parseClassDeclarationOrExpression(pos, hasJSDoc, modifiers, SyntaxKind.ClassDeclaration) as AstClassDeclaration; } - function parseClassDeclarationOrExpression(pos: number, hasJSDoc: boolean, modifiers: NodeArray | undefined, kind: ClassLikeDeclaration["kind"]): ClassLikeDeclaration { + function parseClassDeclarationOrExpression(pos: number, hasJSDoc: boolean, modifiers: AstNodeArray | undefined, kind: AstClassLikeDeclaration["kind"]): AstClassLikeDeclaration { const savedAwaitContext = inAwaitContext(); parseExpected(SyntaxKind.ClassKeyword); // 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, isExportModifier)) setAwaitContext(/*value*/ true); + if (some(modifiers?.items, isAstExportModifier)) setAwaitContext(/*value*/ true); const heritageClauses = parseHeritageClauses(); let members; @@ -8087,7 +7234,7 @@ namespace Parser { parseExpected(SyntaxKind.CloseBraceToken); } else { - members = createMissingList(); + members = createMissingList(); } setAwaitContext(savedAwaitContext); const node = kind === SyntaxKind.ClassDeclaration @@ -8096,7 +7243,7 @@ namespace Parser { return withJSDoc(finishNode(node, pos), hasJSDoc); } - function parseNameOfClassDeclarationOrExpression(): Identifier | undefined { + function parseNameOfClassDeclarationOrExpression(): AstIdentifier | undefined { // implements is a future reserved word so // 'class implements' might mean either // - class expression with omitted name, 'implements' starts heritage clause @@ -8111,7 +7258,7 @@ namespace Parser { return token() === SyntaxKind.ImplementsKeyword && lookAhead(nextTokenIsIdentifierOrKeyword); } - function parseHeritageClauses(): NodeArray | undefined { + function parseHeritageClauses(): AstNodeArray | undefined { // ClassTail[Yield,Await] : (Modified) See 14.5 // ClassHeritage[?Yield,?Await]opt { ClassBody[?Yield,?Await]opt } @@ -8122,7 +7269,7 @@ namespace Parser { return undefined; } - function parseHeritageClause(): HeritageClause { + function parseHeritageClause(): AstHeritageClause { const pos = getNodePos(); const tok = token(); Debug.assert(tok === SyntaxKind.ExtendsKeyword || tok === SyntaxKind.ImplementsKeyword); // isListElement() should ensure this. @@ -8131,17 +7278,17 @@ namespace Parser { return finishNode(factory.createHeritageClause(tok, types), pos); } - function parseExpressionWithTypeArguments(): ExpressionWithTypeArguments { + function parseExpressionWithTypeArguments(): AstExpressionWithTypeArguments { const pos = getNodePos(); const expression = parseLeftHandSideExpressionOrHigher(); if (expression.kind === SyntaxKind.ExpressionWithTypeArguments) { - return expression as ExpressionWithTypeArguments; + return expression as AstExpressionWithTypeArguments; } const typeArguments = tryParseTypeArguments(); return finishNode(factory.createExpressionWithTypeArguments(expression, typeArguments), pos); } - function tryParseTypeArguments(): NodeArray | undefined { + function tryParseTypeArguments(): AstNodeArray | undefined { return token() === SyntaxKind.LessThanToken ? parseBracketedList(ParsingContext.TypeArguments, parseType, SyntaxKind.LessThanToken, SyntaxKind.GreaterThanToken) : undefined; } @@ -8150,11 +7297,11 @@ namespace Parser { return token() === SyntaxKind.ExtendsKeyword || token() === SyntaxKind.ImplementsKeyword; } - function parseClassMembers(): NodeArray { + function parseClassMembers(): AstNodeArray { return parseList(ParsingContext.ClassMembers, parseClassElement); } - function parseInterfaceDeclaration(pos: number, hasJSDoc: boolean, modifiers: NodeArray | undefined): InterfaceDeclaration { + function parseInterfaceDeclaration(pos: number, hasJSDoc: boolean, modifiers: AstNodeArray | undefined): AstInterfaceDeclaration { parseExpected(SyntaxKind.InterfaceKeyword); const name = parseIdentifier(); const typeParameters = parseTypeParameters(); @@ -8164,7 +7311,7 @@ namespace Parser { return withJSDoc(finishNode(node, pos), hasJSDoc); } - function parseTypeAliasDeclaration(pos: number, hasJSDoc: boolean, modifiers: NodeArray | undefined): TypeAliasDeclaration { + function parseTypeAliasDeclaration(pos: number, hasJSDoc: boolean, modifiers: AstNodeArray | undefined): AstTypeAliasDeclaration { parseExpected(SyntaxKind.TypeKeyword); if (scanner.hasPrecedingLineBreak()) { parseErrorAtCurrentToken(Diagnostics.Line_break_not_permitted_here); @@ -8182,7 +7329,7 @@ namespace Parser { // In a non-ambient declaration, the grammar allows uninitialized members only in a // ConstantEnumMemberSection, which starts at the beginning of an enum declaration // or any time an integer literal initializer is encountered. - function parseEnumMember(): EnumMember { + function parseEnumMember(): AstEnumMember { const pos = getNodePos(); const hasJSDoc = hasPrecedingJSDocComment(); const name = parsePropertyName(); @@ -8190,7 +7337,7 @@ namespace Parser { return withJSDoc(finishNode(factory.createEnumMember(name, initializer), pos), hasJSDoc); } - function parseEnumDeclaration(pos: number, hasJSDoc: boolean, modifiers: NodeArray | undefined): EnumDeclaration { + function parseEnumDeclaration(pos: number, hasJSDoc: boolean, modifiers: AstNodeArray | undefined): AstEnumDeclaration { parseExpected(SyntaxKind.EnumKeyword); const name = parseIdentifier(); let members; @@ -8199,13 +7346,13 @@ namespace Parser { parseExpected(SyntaxKind.CloseBraceToken); } else { - members = createMissingList(); + members = createMissingList(); } const node = factory.createEnumDeclaration(modifiers, name, members); return withJSDoc(finishNode(node, pos), hasJSDoc); } - function parseModuleBlock(): ModuleBlock { + function parseModuleBlock(): AstModuleBlock { const pos = getNodePos(); let statements; if (parseExpected(SyntaxKind.OpenBraceToken)) { @@ -8213,24 +7360,24 @@ namespace Parser { parseExpected(SyntaxKind.CloseBraceToken); } else { - statements = createMissingList(); + statements = createMissingList(); } return finishNode(factory.createModuleBlock(statements), pos); } - function parseModuleOrNamespaceDeclaration(pos: number, hasJSDoc: boolean, modifiers: NodeArray | undefined, flags: NodeFlags): ModuleDeclaration { + function parseModuleOrNamespaceDeclaration(pos: number, hasJSDoc: boolean, modifiers: AstNodeArray | undefined, flags: NodeFlags): AstModuleDeclaration { // If we are parsing a dotted namespace name, we want to // propagate the 'Namespace' flag across the names if set. const namespaceFlag = flags & NodeFlags.Namespace; const name = flags & NodeFlags.NestedNamespace ? parseIdentifierName() : parseIdentifier(); const body = parseOptional(SyntaxKind.DotToken) - ? parseModuleOrNamespaceDeclaration(getNodePos(), /*hasJSDoc*/ false, /*modifiers*/ undefined, NodeFlags.NestedNamespace | namespaceFlag) as NamespaceDeclaration + ? parseModuleOrNamespaceDeclaration(getNodePos(), /*hasJSDoc*/ false, /*modifiers*/ undefined, NodeFlags.NestedNamespace | namespaceFlag) as AstNamespaceDeclaration : parseModuleBlock(); const node = factory.createModuleDeclaration(modifiers, name, body, flags); return withJSDoc(finishNode(node, pos), hasJSDoc); } - function parseAmbientExternalModuleDeclaration(pos: number, hasJSDoc: boolean, modifiersIn: NodeArray | undefined): ModuleDeclaration { + function parseAmbientExternalModuleDeclaration(pos: number, hasJSDoc: boolean, modifiersIn: AstNodeArray | undefined): AstModuleDeclaration { let flags: NodeFlags = 0; let name; if (token() === SyntaxKind.GlobalKeyword) { @@ -8239,10 +7386,10 @@ namespace Parser { flags |= NodeFlags.GlobalAugmentation; } else { - name = parseLiteralNode() as StringLiteral; - name.text = internIdentifier(name.text); + name = parseLiteralNode() as AstStringLiteral; + name.data.text = internIdentifier(name.data.text); } - let body: ModuleBlock | undefined; + let body: AstModuleBlock | undefined; if (token() === SyntaxKind.OpenBraceToken) { body = parseModuleBlock(); } @@ -8253,7 +7400,7 @@ namespace Parser { return withJSDoc(finishNode(node, pos), hasJSDoc); } - function parseModuleDeclaration(pos: number, hasJSDoc: boolean, modifiersIn: NodeArray | undefined): ModuleDeclaration { + function parseModuleDeclaration(pos: number, hasJSDoc: boolean, modifiersIn: AstNodeArray | undefined): AstModuleDeclaration { let flags: NodeFlags = 0; if (token() === SyntaxKind.GlobalKeyword) { // global augmentation @@ -8288,31 +7435,31 @@ namespace Parser { return nextToken() === SyntaxKind.SlashToken; } - function parseNamespaceExportDeclaration(pos: number, hasJSDoc: boolean, modifiers: NodeArray | undefined): NamespaceExportDeclaration { + function parseNamespaceExportDeclaration(pos: number, hasJSDoc: boolean, modifiers: AstNodeArray | undefined): AstNamespaceExportDeclaration { parseExpected(SyntaxKind.AsKeyword); parseExpected(SyntaxKind.NamespaceKeyword); const name = parseIdentifier(); parseSemicolon(); const node = factory.createNamespaceExportDeclaration(name); // NamespaceExportDeclaration nodes cannot have decorators or modifiers, so we attach them here so we can report them in the grammar checker - (node as Mutable).modifiers = modifiers; + node.data.modifiers = modifiers; return withJSDoc(finishNode(node, pos), hasJSDoc); } - function parseImportDeclarationOrImportEqualsDeclaration(pos: number, hasJSDoc: boolean, modifiers: NodeArray | undefined): ImportEqualsDeclaration | ImportDeclaration { + function parseImportDeclarationOrImportEqualsDeclaration(pos: number, hasJSDoc: boolean, modifiers: AstNodeArray | undefined): AstImportEqualsDeclaration | AstImportDeclaration { parseExpected(SyntaxKind.ImportKeyword); const afterImportPos = scanner.getTokenFullStart(); // We don't parse the identifier here in await context, instead we will report a grammar error in the checker. - let identifier: Identifier | undefined; + let identifier: AstIdentifier | undefined; if (isIdentifier()) { identifier = parseIdentifier(); } let isTypeOnly = false; if ( - identifier?.escapedText === "type" && + identifier?.data.escapedText === "type" && (token() !== SyntaxKind.FromKeyword || isIdentifier() && lookAhead(nextTokenIsFromKeywordOrEqualsToken)) && (isIdentifier() || tokenAfterImportDefinitelyProducesImportDeclaration()) ) { @@ -8333,11 +7480,11 @@ namespace Parser { return withJSDoc(finishNode(node, pos), hasJSDoc); } - function tryParseImportClause(identifier: Identifier | undefined, pos: number, isTypeOnly: boolean, skipJsDocLeadingAsterisks = false) { + function tryParseImportClause(identifier: AstIdentifier | undefined, pos: number, isTypeOnly: boolean, skipJsDocLeadingAsterisks = false) { // ImportDeclaration: // import ImportClause from ModuleSpecifier ; // import ModuleSpecifier; - let importClause: ImportClause | undefined; + let importClause: AstImportClause | undefined; if ( identifier || // import id token() === SyntaxKind.AsteriskToken || // import * @@ -8358,7 +7505,7 @@ namespace Parser { function parseImportAttribute() { const pos = getNodePos(); - const name = tokenIsIdentifierOrKeyword(token()) ? parseIdentifierName() : parseLiteralLikeNode(SyntaxKind.StringLiteral) as StringLiteral; + const name = tokenIsIdentifierOrKeyword(token()) ? parseIdentifierName() : parseLiteralLikeNode(SyntaxKind.StringLiteral) as AstStringLiteral; parseExpected(SyntaxKind.ColonToken); const value = parseAssignmentExpressionOrHigher(/*allowReturnTypeInArrowFunction*/ true); return finishNode(factory.createImportAttribute(name, value), pos); @@ -8400,7 +7547,7 @@ namespace Parser { return token() === SyntaxKind.CommaToken || token() === SyntaxKind.FromKeyword; } - function parseImportEqualsDeclaration(pos: number, hasJSDoc: boolean, modifiers: NodeArray | undefined, identifier: Identifier, isTypeOnly: boolean): ImportEqualsDeclaration { + function parseImportEqualsDeclaration(pos: number, hasJSDoc: boolean, modifiers: AstNodeArray | undefined, identifier: AstIdentifier, isTypeOnly: boolean): AstImportEqualsDeclaration { parseExpected(SyntaxKind.EqualsToken); const moduleReference = parseModuleReference(); parseSemicolon(); @@ -8409,7 +7556,7 @@ namespace Parser { return finished; } - function parseImportClause(identifier: Identifier | undefined, pos: number, isTypeOnly: boolean, skipJsDocLeadingAsterisks: boolean) { + function parseImportClause(identifier: AstIdentifier | undefined, pos: number, isTypeOnly: boolean, skipJsDocLeadingAsterisks: boolean) { // ImportClause: // ImportedDefaultBinding // NameSpaceImport @@ -8419,7 +7566,7 @@ namespace Parser { // If there was no default import or if there is comma token after default import // parse namespace or named imports - let namedBindings: NamespaceImport | NamedImports | undefined; + let namedBindings: AstNamespaceImport | AstNamedImports | undefined; if ( !identifier || parseOptional(SyntaxKind.CommaToken) @@ -8447,10 +7594,10 @@ namespace Parser { return finishNode(factory.createExternalModuleReference(expression), pos); } - function parseModuleSpecifier(): Expression { + function parseModuleSpecifier(): AstExpression { if (token() === SyntaxKind.StringLiteral) { const result = parseLiteralNode(); - result.text = internIdentifier(result.text); + result.data.text = internIdentifier(result.data.text); return result; } else { @@ -8461,7 +7608,7 @@ namespace Parser { } } - function parseNamespaceImport(): NamespaceImport { + function parseNamespaceImport(): AstNamespaceImport { // NameSpaceImport: // * as ImportedBinding const pos = getNodePos(); @@ -8475,13 +7622,13 @@ namespace Parser { return tokenIsIdentifierOrKeyword(token()) || token() === SyntaxKind.StringLiteral; } - function parseModuleExportName(parseName: () => Identifier): ModuleExportName { - return token() === SyntaxKind.StringLiteral ? parseLiteralNode() as StringLiteral : parseName(); + function parseModuleExportName(parseName: () => AstIdentifier): AstModuleExportName { + return token() === SyntaxKind.StringLiteral ? parseLiteralNode() as AstStringLiteral : parseName(); } - function parseNamedImportsOrExports(kind: SyntaxKind.NamedImports): NamedImports; - function parseNamedImportsOrExports(kind: SyntaxKind.NamedExports): NamedExports; - function parseNamedImportsOrExports(kind: SyntaxKind): NamedImportsOrExports { + function parseNamedImportsOrExports(kind: SyntaxKind.NamedImports): AstNamedImports; + function parseNamedImportsOrExports(kind: SyntaxKind.NamedExports): AstNamedExports; + function parseNamedImportsOrExports(kind: SyntaxKind): AstNamedImports | AstNamedExports { const pos = getNodePos(); // NamedImports: @@ -8500,14 +7647,14 @@ namespace Parser { function parseExportSpecifier() { const hasJSDoc = hasPrecedingJSDocComment(); - return withJSDoc(parseImportOrExportSpecifier(SyntaxKind.ExportSpecifier) as ExportSpecifier, hasJSDoc); + return withJSDoc(parseImportOrExportSpecifier(SyntaxKind.ExportSpecifier) as AstExportSpecifier, hasJSDoc); } function parseImportSpecifier() { - return parseImportOrExportSpecifier(SyntaxKind.ImportSpecifier) as ImportSpecifier; + return parseImportOrExportSpecifier(SyntaxKind.ImportSpecifier) as AstImportSpecifier; } - function parseImportOrExportSpecifier(kind: SyntaxKind): ImportOrExportSpecifier { + function parseImportOrExportSpecifier(kind: SyntaxKind): AstImportSpecifier | AstExportSpecifier { const pos = getNodePos(); // ImportSpecifier: // BindingIdentifier @@ -8519,10 +7666,10 @@ namespace Parser { let checkIdentifierStart = scanner.getTokenStart(); let checkIdentifierEnd = scanner.getTokenEnd(); let isTypeOnly = false; - let propertyName: ModuleExportName | undefined; + let propertyName: AstModuleExportName | undefined; let canParseAsKeyword = true; let name = parseModuleExportName(parseIdentifierName); - if (name.kind === SyntaxKind.Identifier && name.escapedText === "type") { + if (name.kind === SyntaxKind.Identifier && name.data.escapedText === "type") { // If the first token of an import specifier is 'type', there are a lot of possibilities, // especially if we see 'as' afterwards: // @@ -8581,14 +7728,14 @@ namespace Parser { if (name.kind !== SyntaxKind.Identifier) { // ImportSpecifier casts "name" to Identifier below, so make sure it's an identifier parseErrorAt(skipTrivia(sourceText, name.pos), name.end, Diagnostics.Identifier_expected); - name = setTextRangePosEnd(createMissingNode(SyntaxKind.Identifier, /*reportAtCurrentPosition*/ false), name.pos, name.pos); + name = setTextRangePosEnd(createMissingNode(SyntaxKind.Identifier, /*reportAtCurrentPosition*/ false), name.pos, name.pos); } else if (checkIdentifierIsKeyword) { parseErrorAt(checkIdentifierStart, checkIdentifierEnd, Diagnostics.Identifier_expected); } } const node = kind === SyntaxKind.ImportSpecifier - ? factory.createImportSpecifier(isTypeOnly, propertyName, name as Identifier) + ? factory.createImportSpecifier(isTypeOnly, propertyName, name as AstIdentifier) : factory.createExportSpecifier(isTypeOnly, propertyName, name); return finishNode(node, pos); @@ -8600,16 +7747,16 @@ namespace Parser { } } - function parseNamespaceExport(pos: number): NamespaceExport { + function parseNamespaceExport(pos: number): AstNamespaceExport { return finishNode(factory.createNamespaceExport(parseModuleExportName(parseIdentifierName)), pos); } - function parseExportDeclaration(pos: number, hasJSDoc: boolean, modifiers: NodeArray | undefined): ExportDeclaration { + function parseExportDeclaration(pos: number, hasJSDoc: boolean, modifiers: AstNodeArray | undefined): AstExportDeclaration { const savedAwaitContext = inAwaitContext(); setAwaitContext(/*value*/ true); - let exportClause: NamedExportBindings | undefined; - let moduleSpecifier: Expression | undefined; - let attributes: ImportAttributes | undefined; + let exportClause: AstNamedExportBindings | undefined; + let moduleSpecifier: AstExpression | undefined; + let attributes: AstImportAttributes | undefined; const isTypeOnly = parseOptional(SyntaxKind.TypeKeyword); const namespaceExportPos = getNodePos(); if (parseOptional(SyntaxKind.AsteriskToken)) { @@ -8639,7 +7786,7 @@ namespace Parser { return withJSDoc(finishNode(node, pos), hasJSDoc); } - function parseExportAssignment(pos: number, hasJSDoc: boolean, modifiers: NodeArray | undefined): ExportAssignment { + function parseExportAssignment(pos: number, hasJSDoc: boolean, modifiers: AstNodeArray | undefined): AstExportAssignment { const savedAwaitContext = inAwaitContext(); setAwaitContext(/*value*/ true); let isExportEquals: boolean | undefined; @@ -8701,18 +7848,18 @@ namespace Parser { const jsDocTypeExpression = parseJSDocTypeExpression(); const sourceFile = createSourceFile("file.js", ScriptTarget.Latest, ScriptKind.JS, /*isDeclarationFile*/ false, [], factoryCreateToken(SyntaxKind.EndOfFileToken), NodeFlags.None, noop); - const diagnostics = attachFileToDiagnostics(parseDiagnostics, sourceFile); + const diagnostics = attachFileToDiagnostics(parseDiagnostics, sourceFile.node); // TODO(rbuckton): do not instantiate node if (jsDocDiagnostics) { - sourceFile.jsDocDiagnostics = attachFileToDiagnostics(jsDocDiagnostics, sourceFile); + sourceFile.data.jsDocDiagnostics = attachFileToDiagnostics(jsDocDiagnostics, sourceFile.node); // TODO(rbuckton): do not instantiate node } clearState(); - return jsDocTypeExpression ? { jsDocTypeExpression, diagnostics } : undefined; + return jsDocTypeExpression ? { jsDocTypeExpression: jsDocTypeExpression.node, diagnostics } : undefined; } // Parses out a JSDoc type expression. - export function parseJSDocTypeExpression(mayOmitBraces?: boolean): JSDocTypeExpression { + export function parseJSDocTypeExpression(mayOmitBraces?: boolean): AstJSDocTypeExpression { const pos = getNodePos(); const hasBrace = (mayOmitBraces ? parseOptional : parseExpected)(SyntaxKind.OpenBraceToken); const type = doInsideOfContext(NodeFlags.JSDoc, parseJSDocType); @@ -8725,11 +7872,11 @@ namespace Parser { return finishNode(result, pos); } - export function parseJSDocNameReference(): JSDocNameReference { + export function parseJSDocNameReference(): AstJSDocNameReference { const pos = getNodePos(); const hasBrace = parseOptional(SyntaxKind.OpenBraceToken); const p2 = getNodePos(); - let entityName: EntityName | JSDocMemberName = parseEntityName(/*allowReservedWords*/ false); + let entityName: AstEntityName | AstJSDocMemberName = parseEntityName(/*allowReservedWords*/ false); while (token() === SyntaxKind.PrivateIdentifier) { reScanHashToken(); // rescan #id as # id nextTokenJSDoc(); // then skip the # @@ -8752,10 +7899,10 @@ namespace Parser { const diagnostics = attachFileToDiagnostics(parseDiagnostics, sourceFile); clearState(); - return jsDoc ? { jsDoc, diagnostics } : undefined; + return jsDoc ? { jsDoc: jsDoc.node, diagnostics } : undefined; } - export function parseJSDocComment(parent: HasJSDoc, start: number, length: number): JSDoc | undefined { + export function parseJSDocComment(parent: AstHasJSDoc, start: number, length: number): AstJSDocNode | undefined { const saveToken = currentToken; const saveParseDiagnosticsLength = parseDiagnostics.length; const saveParseErrorBeforeNextFinishedNode = parseErrorBeforeNextFinishedNode; @@ -8788,7 +7935,7 @@ namespace Parser { CallbackParameter = 1 << 2, } - function parseJSDocCommentWorker(start = 0, length: number | undefined): JSDoc | undefined { + function parseJSDocCommentWorker(start = 0, length: number | undefined): AstJSDocNode | undefined { const content = sourceText; const end = length === undefined ? content.length : start + length; length = end - start; @@ -8802,13 +7949,13 @@ namespace Parser { return undefined; } - let tags: JSDocTag[]; + let tags: AstJSDocTag[]; let tagsPos: number; let tagsEnd: number; let linkEnd: number; let commentsPos: number | undefined; let comments: string[] = []; - const parts: JSDocComment[] = []; + const parts: AstJSDocComment[] = []; const saveParsingContext = parsingContext; parsingContext |= 1 << ParsingContext.JSDocComment; @@ -9006,8 +8153,8 @@ namespace Parser { const tagName = parseJSDocIdentifierName(/*message*/ undefined); const indentText = skipWhitespaceOrAsterisk(); - let tag: JSDocTag | undefined; - switch (tagName.escapedText) { + let tag: AstJSDocTag | undefined; + switch (tagName.data.escapedText) { case "author": tag = parseAuthorTag(start, tagName, margin, indentText); break; @@ -9098,10 +8245,10 @@ namespace Parser { return parseTagComments(margin, indentText.slice(margin)); } - function parseTagComments(indent: number, initialMargin?: string): string | NodeArray | undefined { + function parseTagComments(indent: number, initialMargin?: string): string | AstNodeArray | undefined { const commentsPos = getNodePos(); let comments: string[] = []; - const parts: JSDocComment[] = []; + const parts: AstJSDocComment[] = []; let linkEnd; let state = JSDocState.BeginningOfLine; let margin: number | undefined; @@ -9235,9 +8382,9 @@ namespace Parser { if (tokenIsIdentifierOrKeyword(token())) { const pos = getNodePos(); - let name: EntityName | JSDocMemberName = parseIdentifierName(); + let name: AstEntityName | AstJSDocMemberName = parseIdentifierName(); while (parseOptional(SyntaxKind.DotToken)) { - name = finishNode(factory.createQualifiedName(name, token() === SyntaxKind.PrivateIdentifier ? createMissingNode(SyntaxKind.Identifier, /*reportAtCurrentPosition*/ false) : parseIdentifierName()), pos); + name = finishNode(factory.createQualifiedName(name, token() === SyntaxKind.PrivateIdentifier ? createMissingNode(SyntaxKind.Identifier, /*reportAtCurrentPosition*/ false) : parseIdentifierName()), pos); } while (token() === SyntaxKind.PrivateIdentifier) { reScanHashToken(); @@ -9265,11 +8412,11 @@ namespace Parser { return kind === "link" || kind === "linkcode" || kind === "linkplain"; } - function parseUnknownTag(start: number, tagName: Identifier, indent: number, indentText: string) { + function parseUnknownTag(start: number, tagName: AstIdentifier, indent: number, indentText: string) { return finishNode(factory.createJSDocUnknownTag(tagName, parseTrailingTagComments(start, getNodePos(), indent, indentText)), start); } - function addTag(tag: JSDocTag | undefined): void { + function addTag(tag: AstJSDocTag | undefined): void { if (!tag) { return; } @@ -9283,12 +8430,12 @@ namespace Parser { tagsEnd = tag.end; } - function tryParseTypeExpression(): JSDocTypeExpression | undefined { + function tryParseTypeExpression(): AstJSDocTypeExpression | undefined { skipWhitespaceOrAsterisk(); return token() === SyntaxKind.OpenBraceToken ? parseJSDocTypeExpression() : undefined; } - function parseBracketNameInPropertyAndParamTag(): { name: EntityName; isBracketed: boolean; } { + function parseBracketNameInPropertyAndParamTag(): { name: AstEntityName; isBracketed: boolean; } { // Looking for something like '[foo]', 'foo', '[foo.bar]' or 'foo.bar' const isBracketed = parseOptionalJsdoc(SyntaxKind.OpenBracketToken); if (isBracketed) { @@ -9313,18 +8460,18 @@ namespace Parser { return { name, isBracketed }; } - function isObjectOrObjectArrayTypeReference(node: TypeNode): boolean { + function isObjectOrObjectArrayTypeReference(node: AstTypeNode): boolean { switch (node.kind) { case SyntaxKind.ObjectKeyword: return true; case SyntaxKind.ArrayType: - return isObjectOrObjectArrayTypeReference((node as ArrayTypeNode).elementType); + return isObjectOrObjectArrayTypeReference((node as AstArrayTypeNode).data.elementType); default: - return isTypeReferenceNode(node) && isIdentifierNode(node.typeName) && node.typeName.escapedText === "Object" && !node.typeArguments; + return isAstTypeReferenceNode(node) && isAstIdentifier(node.data.typeName) && node.data.typeName.data.escapedText === "Object" && !node.data.typeArguments; } } - function parseParameterOrPropertyTag(start: number, tagName: Identifier, target: PropertyLikeParse, indent: number): JSDocParameterTag | JSDocPropertyTag { + function parseParameterOrPropertyTag(start: number, tagName: AstIdentifier, target: PropertyLikeParse, indent: number): AstJSDocParameterTag | AstJSDocPropertyTag { let typeExpression = tryParseTypeExpression(); let isNameFirst = !typeExpression; skipWhitespaceOrAsterisk(); @@ -9349,38 +8496,38 @@ namespace Parser { return finishNode(result, start); } - function parseNestedTypeLiteral(typeExpression: JSDocTypeExpression | undefined, name: EntityName, target: PropertyLikeParse, indent: number) { - if (typeExpression && isObjectOrObjectArrayTypeReference(typeExpression.type)) { + function parseNestedTypeLiteral(typeExpression: AstJSDocTypeExpression | undefined, name: AstEntityName, target: PropertyLikeParse, indent: number) { + if (typeExpression && isObjectOrObjectArrayTypeReference(typeExpression.data.type)) { const pos = getNodePos(); - let child: JSDocPropertyLikeTag | JSDocTypeTag | JSDocTemplateTag | JSDocThisTag | false; - let children: JSDocPropertyLikeTag[] | undefined; + let child: AstJSDocPropertyLikeTag | AstJSDocTypeTag | AstJSDocTemplateTag | AstJSDocThisTag | false; + let children: AstJSDocPropertyLikeTag[] | undefined; while (child = tryParse(() => parseChildParameterOrPropertyTag(target, indent, name))) { if (child.kind === SyntaxKind.JSDocParameterTag || child.kind === SyntaxKind.JSDocPropertyTag) { children = append(children, child); } else if (child.kind === SyntaxKind.JSDocTemplateTag) { - parseErrorAtRange(child.tagName, Diagnostics.A_JSDoc_template_tag_may_not_follow_a_typedef_callback_or_overload_tag); + parseErrorAtRange(child.data.tagName, Diagnostics.A_JSDoc_template_tag_may_not_follow_a_typedef_callback_or_overload_tag); } } if (children) { - const literal = finishNode(factory.createJSDocTypeLiteral(children, typeExpression.type.kind === SyntaxKind.ArrayType), pos); + const literal = finishNode(factory.createJSDocTypeLiteral(children, typeExpression.data.type.kind === SyntaxKind.ArrayType), pos); return finishNode(factory.createJSDocTypeExpression(literal), pos); } } } - function parseReturnTag(start: number, tagName: Identifier, indent: number, indentText: string): JSDocReturnTag { - if (some(tags, isJSDocReturnTag)) { - parseErrorAt(tagName.pos, scanner.getTokenStart(), Diagnostics._0_tag_already_specified, unescapeLeadingUnderscores(tagName.escapedText)); + function parseReturnTag(start: number, tagName: AstIdentifier, indent: number, indentText: string): AstJSDocReturnTag { + if (some(tags, isAstJSDocReturnTag)) { + parseErrorAt(tagName.pos, scanner.getTokenStart(), Diagnostics._0_tag_already_specified, unescapeLeadingUnderscores(tagName.data.escapedText)); } const typeExpression = tryParseTypeExpression(); return finishNode(factory.createJSDocReturnTag(tagName, typeExpression, parseTrailingTagComments(start, getNodePos(), indent, indentText)), start); } - function parseTypeTag(start: number, tagName: Identifier, indent?: number, indentText?: string): JSDocTypeTag { - if (some(tags, isJSDocTypeTag)) { - parseErrorAt(tagName.pos, scanner.getTokenStart(), Diagnostics._0_tag_already_specified, unescapeLeadingUnderscores(tagName.escapedText)); + function parseTypeTag(start: number, tagName: AstIdentifier, indent?: number, indentText?: string): AstJSDocTypeTag { + if (some(tags, isAstJSDocTypeTag)) { + parseErrorAt(tagName.pos, scanner.getTokenStart(), Diagnostics._0_tag_already_specified, unescapeLeadingUnderscores(tagName.data.escapedText)); } const typeExpression = parseJSDocTypeExpression(/*mayOmitBraces*/ true); @@ -9388,7 +8535,7 @@ namespace Parser { return finishNode(factory.createJSDocTypeTag(tagName, typeExpression, comments), start); } - function parseSeeTag(start: number, tagName: Identifier, indent?: number, indentText?: string): JSDocSeeTag { + function parseSeeTag(start: number, tagName: AstIdentifier, indent?: number, indentText?: string): AstJSDocSeeTag { const isMarkdownOrJSDocLink = token() === SyntaxKind.OpenBracketToken || lookAhead(() => nextTokenJSDoc() === SyntaxKind.AtToken && tokenIsIdentifierOrKeyword(nextTokenJSDoc()) && isJSDocLinkTag(scanner.getTokenValue())); const nameExpression = isMarkdownOrJSDocLink ? undefined : parseJSDocNameReference(); @@ -9396,13 +8543,13 @@ namespace Parser { return finishNode(factory.createJSDocSeeTag(tagName, nameExpression, comments), start); } - function parseThrowsTag(start: number, tagName: Identifier, indent: number, indentText: string): JSDocThrowsTag { + function parseThrowsTag(start: number, tagName: AstIdentifier, indent: number, indentText: string): AstJSDocThrowsTag { const typeExpression = tryParseTypeExpression(); const comment = parseTrailingTagComments(start, getNodePos(), indent, indentText); return finishNode(factory.createJSDocThrowsTag(tagName, typeExpression, comment), start); } - function parseAuthorTag(start: number, tagName: Identifier, indent: number, indentText: string): JSDocAuthorTag { + function parseAuthorTag(start: number, tagName: AstIdentifier, indent: number, indentText: string): AstJSDocAuthorTag { const commentStart = getNodePos(); const textOnly = parseAuthorNameAndEmail(); let commentEnd = scanner.getTokenFullStart(); @@ -9411,12 +8558,12 @@ namespace Parser { commentEnd = scanner.getTokenFullStart(); } const allParts = typeof comments !== "string" - ? createNodeArray(concatenate([finishNode(textOnly, commentStart, commentEnd)], comments) as JSDocComment[], commentStart) // cast away readonly - : textOnly.text + comments; + ? createNodeArray(concatenate([finishNode(textOnly, commentStart, commentEnd)], comments?.items) as AstJSDocComment[], commentStart) // cast away readonly + : textOnly.data.text + comments; return finishNode(factory.createJSDocAuthorTag(tagName, allParts), start); } - function parseAuthorNameAndEmail(): JSDocText { + function parseAuthorNameAndEmail(): AstJSDocText { const comments: string[] = []; let inEmail = false; let token = scanner.getToken(); @@ -9439,26 +8586,26 @@ namespace Parser { return factory.createJSDocText(comments.join("")); } - function parseImplementsTag(start: number, tagName: Identifier, margin: number, indentText: string): JSDocImplementsTag { + function parseImplementsTag(start: number, tagName: AstIdentifier, margin: number, indentText: string): AstJSDocImplementsTag { const className = parseExpressionWithTypeArgumentsForAugments(); return finishNode(factory.createJSDocImplementsTag(tagName, className, parseTrailingTagComments(start, getNodePos(), margin, indentText)), start); } - function parseAugmentsTag(start: number, tagName: Identifier, margin: number, indentText: string): JSDocAugmentsTag { + function parseAugmentsTag(start: number, tagName: AstIdentifier, margin: number, indentText: string): AstJSDocAugmentsTag { const className = parseExpressionWithTypeArgumentsForAugments(); return finishNode(factory.createJSDocAugmentsTag(tagName, className, parseTrailingTagComments(start, getNodePos(), margin, indentText)), start); } - function parseSatisfiesTag(start: number, tagName: Identifier, margin: number, indentText: string): JSDocSatisfiesTag { + function parseSatisfiesTag(start: number, tagName: AstIdentifier, margin: number, indentText: string): AstJSDocSatisfiesTag { const typeExpression = parseJSDocTypeExpression(/*mayOmitBraces*/ false); const comments = margin !== undefined && indentText !== undefined ? parseTrailingTagComments(start, getNodePos(), margin, indentText) : undefined; return finishNode(factory.createJSDocSatisfiesTag(tagName, typeExpression, comments), start); } - function parseImportTag(start: number, tagName: Identifier, margin: number, indentText: string): JSDocImportTag { + function parseImportTag(start: number, tagName: AstIdentifier, margin: number, indentText: string): AstJSDocImportTag { const afterImportTagPos = scanner.getTokenFullStart(); - let identifier: Identifier | undefined; + let identifier: AstIdentifier | undefined; if (isIdentifier()) { identifier = parseIdentifier(); } @@ -9471,14 +8618,14 @@ namespace Parser { return finishNode(factory.createJSDocImportTag(tagName, importClause, moduleSpecifier, attributes, comments), start); } - function parseExpressionWithTypeArgumentsForAugments(): ExpressionWithTypeArguments & { expression: Identifier | PropertyAccessEntityNameExpression; } { + function parseExpressionWithTypeArgumentsForAugments(): AstJSDocClassReference { const usedBrace = parseOptional(SyntaxKind.OpenBraceToken); const pos = getNodePos(); const expression = parsePropertyAccessEntityNameExpression(); scanner.setSkipJsDocLeadingAsterisks(true); const typeArguments = tryParseTypeArguments(); scanner.setSkipJsDocLeadingAsterisks(false); - const node = factory.createExpressionWithTypeArguments(expression, typeArguments) as ExpressionWithTypeArguments & { expression: Identifier | PropertyAccessEntityNameExpression; }; + const node = factory.createExpressionWithTypeArguments(expression, typeArguments) as AstJSDocClassReference; const res = finishNode(node, pos); if (usedBrace) { parseExpected(SyntaxKind.CloseBraceToken); @@ -9488,32 +8635,32 @@ namespace Parser { function parsePropertyAccessEntityNameExpression() { const pos = getNodePos(); - let node: Identifier | PropertyAccessEntityNameExpression = parseJSDocIdentifierName(); + let node: AstEntityNameExpression = parseJSDocIdentifierName(); while (parseOptional(SyntaxKind.DotToken)) { const name = parseJSDocIdentifierName(); - node = finishNode(factoryCreatePropertyAccessExpression(node, name), pos) as PropertyAccessEntityNameExpression; + node = finishNode(factoryCreatePropertyAccessExpression(node, name), pos) as AstPropertyAccessEntityNameExpression; } return node; } - function parseSimpleTag(start: number, createTag: (tagName: Identifier | undefined, comment?: string | NodeArray) => JSDocTag, tagName: Identifier, margin: number, indentText: string): JSDocTag { + function parseSimpleTag(start: number, createTag: (tagName: AstIdentifier | undefined, comment?: string | AstNodeArray) => AstJSDocTag, tagName: AstIdentifier, margin: number, indentText: string): AstJSDocTag { return finishNode(createTag(tagName, parseTrailingTagComments(start, getNodePos(), margin, indentText)), start); } - function parseThisTag(start: number, tagName: Identifier, margin: number, indentText: string): JSDocThisTag { + function parseThisTag(start: number, tagName: AstIdentifier, margin: number, indentText: string): AstJSDocThisTag { const typeExpression = parseJSDocTypeExpression(/*mayOmitBraces*/ true); skipWhitespace(); return finishNode(factory.createJSDocThisTag(tagName, typeExpression, parseTrailingTagComments(start, getNodePos(), margin, indentText)), start); } - function parseEnumTag(start: number, tagName: Identifier, margin: number, indentText: string): JSDocEnumTag { + function parseEnumTag(start: number, tagName: AstIdentifier, margin: number, indentText: string): AstJSDocEnumTag { const typeExpression = parseJSDocTypeExpression(/*mayOmitBraces*/ true); skipWhitespace(); return finishNode(factory.createJSDocEnumTag(tagName, typeExpression, parseTrailingTagComments(start, getNodePos(), margin, indentText)), start); } - function parseTypedefTag(start: number, tagName: Identifier, indent: number, indentText: string): JSDocTypedefTag { - let typeExpression: JSDocTypeExpression | JSDocTypeLiteral | undefined = tryParseTypeExpression(); + function parseTypedefTag(start: number, tagName: AstIdentifier, indent: number, indentText: string): AstJSDocTypedefTag { + let typeExpression: AstJSDocTypeExpression | AstJSDocTypeLiteral | undefined = tryParseTypeExpression(); skipWhitespaceOrAsterisk(); const fullName = parseJSDocTypeNameWithNamespace(); @@ -9521,10 +8668,10 @@ namespace Parser { let comment = parseTagComments(indent); let end: number | undefined; - if (!typeExpression || isObjectOrObjectArrayTypeReference(typeExpression.type)) { - let child: JSDocTypeTag | JSDocPropertyTag | JSDocTemplateTag | false; - let childTypeTag: JSDocTypeTag | undefined; - let jsDocPropertyTags: JSDocPropertyTag[] | undefined; + if (!typeExpression || isObjectOrObjectArrayTypeReference(typeExpression.data.type)) { + let child: AstJSDocTypeTag | AstJSDocPropertyTag | AstJSDocTemplateTag | false; + let childTypeTag: AstJSDocTypeTag | undefined; + let jsDocPropertyTags: AstJSDocPropertyTag[] | undefined; let hasChildren = false; while (child = tryParse(() => parseChildPropertyTag(indent))) { if (child.kind === SyntaxKind.JSDocTemplateTag) { @@ -9548,10 +8695,10 @@ namespace Parser { } } if (hasChildren) { - const isArrayType = typeExpression && typeExpression.type.kind === SyntaxKind.ArrayType; + const isArrayType = typeExpression && typeExpression.data.type.kind === SyntaxKind.ArrayType; const jsdocTypeLiteral = factory.createJSDocTypeLiteral(jsDocPropertyTags, isArrayType); - typeExpression = childTypeTag && childTypeTag.typeExpression && !isObjectOrObjectArrayTypeReference(childTypeTag.typeExpression.type) ? - childTypeTag.typeExpression : + typeExpression = childTypeTag && childTypeTag.data.typeExpression && !isObjectOrObjectArrayTypeReference(childTypeTag.data.typeExpression.data.type) ? + childTypeTag.data.typeExpression : finishNode(jsdocTypeLiteral, start); end = typeExpression.end; } @@ -9583,23 +8730,23 @@ namespace Parser { typeNameOrNamespaceName, body, nested ? NodeFlags.NestedNamespace : undefined, - ) as JSDocNamespaceDeclaration; + ) as AstJSDocNamespaceDeclaration; return finishNode(jsDocNamespaceNode, start); } if (nested) { - (typeNameOrNamespaceName as Mutable).flags |= NodeFlags.IdentifierIsInJSDocNamespace; + typeNameOrNamespaceName.flags |= NodeFlags.IdentifierIsInJSDocNamespace; } return typeNameOrNamespaceName; } function parseCallbackTagParameters(indent: number) { const pos = getNodePos(); - let child: JSDocParameterTag | JSDocTemplateTag | false; + let child: AstJSDocParameterTag | AstJSDocTemplateTag | false; let parameters; - while (child = tryParse(() => parseChildParameterOrPropertyTag(PropertyLikeParse.CallbackParameter, indent) as JSDocParameterTag | JSDocTemplateTag)) { + while (child = tryParse(() => parseChildParameterOrPropertyTag(PropertyLikeParse.CallbackParameter, indent) as AstJSDocParameterTag | AstJSDocTemplateTag)) { if (child.kind === SyntaxKind.JSDocTemplateTag) { - parseErrorAtRange(child.tagName, Diagnostics.A_JSDoc_template_tag_may_not_follow_a_typedef_callback_or_overload_tag); + parseErrorAtRange(child.data.tagName, Diagnostics.A_JSDoc_template_tag_may_not_follow_a_typedef_callback_or_overload_tag); break; } parameters = append(parameters, child); @@ -9607,20 +8754,20 @@ namespace Parser { return createNodeArray(parameters || [], pos); } - function parseJSDocSignature(start: number, indent: number): JSDocSignature { + function parseJSDocSignature(start: number, indent: number): AstJSDocSignature { const parameters = parseCallbackTagParameters(indent); const returnTag = tryParse(() => { if (parseOptionalJsdoc(SyntaxKind.AtToken)) { const tag = parseTag(indent); if (tag && tag.kind === SyntaxKind.JSDocReturnTag) { - return tag as JSDocReturnTag; + return tag as AstJSDocReturnTag; } } }); return finishNode(factory.createJSDocSignature(/*typeParameters*/ undefined, parameters, returnTag), start); } - function parseCallbackTag(start: number, tagName: Identifier, indent: number, indentText: string): JSDocCallbackTag { + function parseCallbackTag(start: number, tagName: AstIdentifier, indent: number, indentText: string): AstJSDocCallbackTag { const fullName = parseJSDocTypeNameWithNamespace(); skipWhitespace(); let comment = parseTagComments(indent); @@ -9632,7 +8779,7 @@ namespace Parser { return finishNode(factory.createJSDocCallbackTag(tagName, typeExpression, fullName, comment), start, end); } - function parseOverloadTag(start: number, tagName: Identifier, indent: number, indentText: string): JSDocOverloadTag { + function parseOverloadTag(start: number, tagName: AstIdentifier, indent: number, indentText: string): AstJSDocOverloadTag { skipWhitespace(); let comment = parseTagComments(indent); const typeExpression = parseJSDocSignature(start, indent); @@ -9643,24 +8790,24 @@ namespace Parser { return finishNode(factory.createJSDocOverloadTag(tagName, typeExpression, comment), start, end); } - function escapedTextsEqual(a: EntityName, b: EntityName): boolean { - while (!isIdentifierNode(a) || !isIdentifierNode(b)) { - if (!isIdentifierNode(a) && !isIdentifierNode(b) && a.right.escapedText === b.right.escapedText) { - a = a.left; - b = b.left; + 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) { + a = a.data.left; + b = b.data.left; } else { return false; } } - return a.escapedText === b.escapedText; + return a.data.escapedText === b.data.escapedText; } function parseChildPropertyTag(indent: number) { - return parseChildParameterOrPropertyTag(PropertyLikeParse.Property, indent) as JSDocTypeTag | JSDocPropertyTag | JSDocTemplateTag | false; + return parseChildParameterOrPropertyTag(PropertyLikeParse.Property, indent) as AstJSDocTypeTag | AstJSDocPropertyTag | AstJSDocTemplateTag | false; } - function parseChildParameterOrPropertyTag(target: PropertyLikeParse, indent: number, name?: EntityName): JSDocTypeTag | JSDocPropertyTag | JSDocParameterTag | JSDocTemplateTag | JSDocThisTag | false { + function parseChildParameterOrPropertyTag(target: PropertyLikeParse, indent: number, name?: AstEntityName): AstJSDocTypeTag | AstJSDocPropertyTag | AstJSDocParameterTag | AstJSDocTemplateTag | AstJSDocThisTag | false { let canParseTag = true; let seenAsterisk = false; while (true) { @@ -9670,7 +8817,7 @@ namespace Parser { const child = tryParseChildTag(target, indent); if ( child && (child.kind === SyntaxKind.JSDocParameterTag || child.kind === SyntaxKind.JSDocPropertyTag) && - name && (isIdentifierNode(child.name) || !escapedTextsEqual(name, child.name.left)) + name && (isAstIdentifier(child.data.name) || !escapedTextsEqual(name, child.data.name.data.left)) ) { return false; } @@ -9697,7 +8844,7 @@ namespace Parser { } } - function tryParseChildTag(target: PropertyLikeParse, indent: number): JSDocTypeTag | JSDocPropertyTag | JSDocParameterTag | JSDocTemplateTag | JSDocThisTag | false { + function tryParseChildTag(target: PropertyLikeParse, indent: number): AstJSDocTypeTag | AstJSDocPropertyTag | AstJSDocParameterTag | AstJSDocTemplateTag | AstJSDocThisTag | false { Debug.assert(token() === SyntaxKind.AtToken); const start = scanner.getTokenFullStart(); nextTokenJSDoc(); @@ -9705,7 +8852,7 @@ namespace Parser { const tagName = parseJSDocIdentifierName(); const indentText = skipWhitespaceOrAsterisk(); let t: PropertyLikeParse; - switch (tagName.escapedText) { + switch (tagName.data.escapedText) { case "type": return target === PropertyLikeParse.Property && parseTypeTag(start, tagName); case "prop": @@ -9739,7 +8886,7 @@ namespace Parser { const modifiers = parseModifiers(/*allowDecorators*/ false, /*permitConstAsModifier*/ true); const name = parseJSDocIdentifierName(Diagnostics.Unexpected_token_A_type_parameter_name_was_expected_without_curly_braces); - let defaultType: TypeNode | undefined; + let defaultType: AstTypeNode | undefined; if (isBracketed) { skipWhitespace(); parseExpected(SyntaxKind.EqualsToken); @@ -9768,7 +8915,7 @@ namespace Parser { return createNodeArray(typeParameters, pos); } - function parseTemplateTag(start: number, tagName: Identifier, indent: number, indentText: string): JSDocTemplateTag { + function parseTemplateTag(start: number, tagName: AstIdentifier, indent: number, indentText: string): AstJSDocTemplateTag { // The template tag looks like one of the following: // @template T,U,V // @template {Constraint} T @@ -9793,8 +8940,8 @@ namespace Parser { return false; } - function parseJSDocEntityName(): EntityName { - let entity: EntityName = parseJSDocIdentifierName(); + function parseJSDocEntityName(): AstEntityName { + let entity: AstEntityName = parseJSDocIdentifierName(); if (parseOptional(SyntaxKind.OpenBracketToken)) { parseExpected(SyntaxKind.CloseBracketToken); // Note that y[] is accepted as an entity name, but the postfix brackets are not saved for checking. @@ -9811,17 +8958,16 @@ namespace Parser { return entity; } - function parseJSDocIdentifierName(message?: DiagnosticMessage): Identifier { + function parseJSDocIdentifierName(message?: DiagnosticMessage): AstIdentifier { if (!tokenIsIdentifierOrKeyword(token())) { - return createMissingNode(SyntaxKind.Identifier, /*reportAtCurrentPosition*/ !message, message || Diagnostics.Identifier_expected); + return createMissingNode(SyntaxKind.Identifier, /*reportAtCurrentPosition*/ !message, message || Diagnostics.Identifier_expected); } identifierCount++; const start = scanner.getTokenStart(); const end = scanner.getTokenEnd(); - const originalKeywordKind = token(); const text = internIdentifier(scanner.getTokenValue()); - const result = finishNode(factoryCreateIdentifier(text, originalKeywordKind), start, end); + const result = finishNode(factoryCreateIdentifier(text), start, end); nextTokenJSDoc(); return result; } @@ -9829,27 +8975,27 @@ namespace Parser { } } -const incrementallyParsedFiles = new WeakSet(); +const incrementallyParsedFiles = new WeakSet(); -function markAsIncrementallyParsed(sourceFile: SourceFile) { +function markAsIncrementallyParsed(sourceFile: AstSourceFile) { if (incrementallyParsedFiles.has(sourceFile)) { Debug.fail("Source file has already been incrementally parsed"); } incrementallyParsedFiles.add(sourceFile); } -const intersectingChangeSet = new WeakSet>(); +const intersectingChangeSet = new WeakSet>(); -function intersectsIncrementalChange(node: Node | NodeArray): boolean { +function intersectsIncrementalChange(node: AstNode | AstNodeArray): boolean { return intersectingChangeSet.has(node); } -function markAsIntersectingIncrementalChange(node: Node | NodeArray) { +function markAsIntersectingIncrementalChange(node: AstNode | AstNodeArray) { intersectingChangeSet.add(node); } namespace IncrementalParser { - export function updateSourceFile(sourceFile: SourceFile, newText: string, textChangeRange: TextChangeRange, aggressiveChecks: boolean): SourceFile { + export function updateSourceFile(sourceFile: AstSourceFile, newText: string, textChangeRange: TextChangeRange, aggressiveChecks: boolean): AstSourceFile { aggressiveChecks = aggressiveChecks || Debug.shouldAssert(AssertionLevel.Aggressive); checkChangeRange(sourceFile, newText, textChangeRange, aggressiveChecks); @@ -9858,10 +9004,10 @@ namespace IncrementalParser { return sourceFile; } - if (sourceFile.statements.length === 0) { + if (sourceFile.data.statements.items.length === 0) { // If we don't have any statements in the current source file, then there's no real // way to incrementally parse. So just do a full parse instead. - return Parser.parseSourceFile(sourceFile.fileName, newText, sourceFile.languageVersion, /*syntaxCursor*/ undefined, /*setParentNodes*/ true, sourceFile.scriptKind, sourceFile.setExternalModuleIndicator, sourceFile.jsDocParsingMode); + return Parser.parseSourceFile(sourceFile.data.fileName, newText, sourceFile.data.languageVersion, /*syntaxCursor*/ undefined, /*setParentNodes*/ true, sourceFile.data.scriptKind, sourceFile.data.setExternalModuleIndicator, sourceFile.data.jsDocParsingMode); } // Make sure we're not trying to incrementally update a source file more than once. Once @@ -9872,7 +9018,7 @@ namespace IncrementalParser { // tree at all is not possible as far too much of it may violate invariants. markAsIncrementallyParsed(sourceFile); Parser.fixupParentReferences(sourceFile); - const oldText = sourceFile.text; + const oldText = sourceFile.data.text; const syntaxCursor = createSyntaxCursor(sourceFile); // Make the actual change larger so that we know to reparse anything whose lookahead @@ -9922,10 +9068,10 @@ namespace IncrementalParser { // inconsistent tree. Setting the parents on the new tree should be very fast. We // will immediately bail out of walking any subtrees when we can see that their parents // are already correct. - const result = Parser.parseSourceFile(sourceFile.fileName, newText, sourceFile.languageVersion, syntaxCursor, /*setParentNodes*/ true, sourceFile.scriptKind, sourceFile.setExternalModuleIndicator, sourceFile.jsDocParsingMode); - result.commentDirectives = getNewCommentDirectives( - sourceFile.commentDirectives, - result.commentDirectives, + const result = Parser.parseSourceFile(sourceFile.data.fileName, newText, sourceFile.data.languageVersion, syntaxCursor, /*setParentNodes*/ true, sourceFile.data.scriptKind, sourceFile.data.setExternalModuleIndicator, sourceFile.data.jsDocParsingMode); + result.data.commentDirectives = getNewCommentDirectives( + sourceFile.data.commentDirectives, + result.data.commentDirectives, changeRange.span.start, textSpanEnd(changeRange.span), delta, @@ -9933,8 +9079,8 @@ namespace IncrementalParser { newText, aggressiveChecks, ); - result.impliedNodeFormat = sourceFile.impliedNodeFormat; - transferSourceFileChildren(sourceFile, result); + result.data.impliedNodeFormat = sourceFile.data.impliedNodeFormat; + transferSourceFileChildren(sourceFile.node, result.node); // TODO(rbuckton): do not instantiate .node return result; } @@ -9987,18 +9133,22 @@ namespace IncrementalParser { } } - function moveElementEntirelyPastChangeRange(element: Node, origSourceFile: SourceFile, isArray: false, delta: number, oldText: string, newText: string, aggressiveChecks: boolean): void; - function moveElementEntirelyPastChangeRange(element: NodeArray, origSourceFile: SourceFile, isArray: true, delta: number, oldText: string, newText: string, aggressiveChecks: boolean): void; - function moveElementEntirelyPastChangeRange(element: Node | NodeArray, origSourceFile: SourceFile, isArray: boolean, delta: number, oldText: string, newText: string, aggressiveChecks: boolean) { + function moveElementEntirelyPastChangeRange(element: AstNode, origSourceFile: AstSourceFile, isArray: false, delta: number, oldText: string, newText: string, aggressiveChecks: boolean): void; + function moveElementEntirelyPastChangeRange(element: AstNodeArray, origSourceFile: AstSourceFile, isArray: true, delta: number, oldText: string, newText: string, aggressiveChecks: boolean): void; + function moveElementEntirelyPastChangeRange(element: AstNode | AstNodeArray, origSourceFile: AstSourceFile, isArray: boolean, delta: number, oldText: string, newText: string, aggressiveChecks: boolean) { if (isArray) { - visitArray(element as NodeArray); + visitArray(element as AstNodeArray); } else { - visitNode(element as Node); + visitNode(element as AstNode); } return; - function visitNode(node: Node) { + function visitNode(node: Node | AstNode) { + if (!(node instanceof AstNode)) { + node = (node as AstNode["node"]).ast; + } + let text = ""; if (aggressiveChecks && shouldCheckNode(node)) { text = oldText.substring(node.pos, node.end); @@ -10006,7 +9156,7 @@ namespace IncrementalParser { // Ditch any existing LS children we may have created. This way we can avoid // moving them forward. - unsetNodeChildren(node, origSourceFile); + unsetNodeChildren(node.node, origSourceFile.node); // TODO: do not instantiate .node setTextRangePosEnd(node, node.pos + delta, node.end + delta); @@ -10014,25 +9164,29 @@ namespace IncrementalParser { Debug.assert(text === newText.substring(node.pos, node.end)); } - forEachChild(node, visitNode as (node: Node) => void, visitArray as (nodes: NodeArray) => void); - if (hasJSDocNodes(node)) { - for (const jsDocComment of node.jsDoc!) { + forEachChild(node.node, visitNode as (node: Node) => void, visitArray as (nodes: NodeArray) => void); // TODO(rbuckton): do not instantiate .node + if (hasAstJSDocNodes(node)) { + for (const jsDocComment of node.data.jsDoc!) { visitNode(jsDocComment); } } checkNodePositions(node, aggressiveChecks); } - function visitArray(array: NodeArray) { + function visitArray(array: NodeArray | AstNodeArray) { + if (!(array instanceof AstNodeArray)) { + array = (array as AstNodeArray["nodes"]).ast; + } + setTextRangePosEnd(array, array.pos + delta, array.end + delta); - for (const node of array) { + for (const node of array.items) { visitNode(node); } } } - function shouldCheckNode(node: Node) { + function shouldCheckNode(node: AstNode) { switch (node.kind) { case SyntaxKind.StringLiteral: case SyntaxKind.NumericLiteral: @@ -10043,7 +9197,7 @@ namespace IncrementalParser { return false; } - function adjustIntersectingElement(element: Node | NodeArray, changeStart: number, changeRangeOldEnd: number, changeRangeNewEnd: number, delta: number) { + function adjustIntersectingElement(element: AstNode | AstNodeArray, changeStart: number, changeRangeOldEnd: number, changeRangeNewEnd: number, delta: number) { Debug.assert(element.end >= changeStart, "Adjusting an element that was entirely before the change range"); Debug.assert(element.pos <= changeRangeOldEnd, "Adjusting an element that was entirely after the change range"); Debug.assert(element.pos <= element.end); @@ -10118,25 +9272,25 @@ namespace IncrementalParser { setTextRangePosEnd(element, pos, end); } - function checkNodePositions(node: Node, aggressiveChecks: boolean) { + function checkNodePositions(node: AstNode, aggressiveChecks: boolean) { if (aggressiveChecks) { let pos = node.pos; const visitNode = (child: Node) => { Debug.assert(child.pos >= pos); pos = child.end; }; - if (hasJSDocNodes(node)) { - for (const jsDocComment of node.jsDoc!) { + if (hasAstJSDocNodes(node)) { + for (const jsDocComment of node.data.jsDoc!) { visitNode(jsDocComment); } } - forEachChild(node, visitNode); + forEachChild(node.node, visitNode); // TODO: do not instantiate .node Debug.assert(pos <= node.end); } } function updateTokenPositionsAndMarkElements( - sourceFile: SourceFile, + sourceFile: AstSourceFile, changeStart: number, changeRangeOldEnd: number, changeRangeNewEnd: number, @@ -10148,7 +9302,11 @@ namespace IncrementalParser { visitNode(sourceFile); return; - function visitNode(child: Node) { + function visitNode(child: Node | AstNode) { + if (!(child instanceof AstNode)) { + child = (child as AstNode["node"]).ast; + } + Debug.assert(child.pos <= child.end); if (child.pos > changeRangeOldEnd) { // Node is entirely past the change range. We need to move both its pos and @@ -10163,14 +9321,14 @@ namespace IncrementalParser { const fullEnd = child.end; if (fullEnd >= changeStart) { markAsIntersectingIncrementalChange(child); - unsetNodeChildren(child, sourceFile); + unsetNodeChildren(child.node, sourceFile.node); // TODO(rbuckton): do not instantiate .node // Adjust the pos or end (or both) of the intersecting element accordingly. adjustIntersectingElement(child, changeStart, changeRangeOldEnd, changeRangeNewEnd, delta); - forEachChild(child, visitNode as (node: Node) => void, visitArray as (nodes: NodeArray) => void); - if (hasJSDocNodes(child)) { - for (const jsDocComment of child.jsDoc!) { - visitNode(jsDocComment); + forEachChild(child.node, visitNode as (node: Node) => void, visitArray as (nodes: NodeArray) => void); // TODO: do not instantiate .node + if (hasAstJSDocNodes(child)) { // TODO: do not instantiate .node + for (const jsDocComment of child.data.jsDoc!) { + visitNode((jsDocComment as AstJSDocNode["node"]).ast); } } checkNodePositions(child, aggressiveChecks); @@ -10181,7 +9339,11 @@ namespace IncrementalParser { Debug.assert(fullEnd < changeStart); } - function visitArray(array: NodeArray) { + function visitArray(array: NodeArray | AstNodeArray) { + if (!(array instanceof AstNodeArray)) { + array = (array as AstNodeArray["nodes"]).ast; + } + Debug.assert(array.pos <= array.end); if (array.pos > changeRangeOldEnd) { // Array is entirely after the change range. We need to move it, and move any of @@ -10199,7 +9361,7 @@ namespace IncrementalParser { // Adjust the pos or end (or both) of the intersecting array accordingly. adjustIntersectingElement(array, changeStart, changeRangeOldEnd, changeRangeNewEnd, delta); - for (const node of array) { + for (const node of array.items) { visitNode(node); } return; @@ -10210,7 +9372,7 @@ namespace IncrementalParser { } } - function extendToAffectedRange(sourceFile: SourceFile, changeRange: TextChangeRange): TextChangeRange { + function extendToAffectedRange(sourceFile: AstSourceFile, changeRange: TextChangeRange): TextChangeRange { // Consider the following code: // void foo() { /; } // @@ -10242,11 +9404,11 @@ namespace IncrementalParser { return createTextChangeRange(finalSpan, finalLength); } - function findNearestNodeStartingBeforeOrAtPosition(sourceFile: SourceFile, position: number): Node { - let bestResult: Node = sourceFile; - let lastNodeEntirelyBeforePosition: Node | undefined; + function findNearestNodeStartingBeforeOrAtPosition(sourceFile: AstSourceFile, position: number): AstNode { + let bestResult: AstNode = sourceFile; + let lastNodeEntirelyBeforePosition: AstNode | undefined; - forEachChild(sourceFile, visit); + forEachChild(sourceFile.node, visit); // TODO(rbuckton): do not instantiate .node if (lastNodeEntirelyBeforePosition) { const lastChildOfLastEntireNodeBeforePosition = getLastDescendant(lastNodeEntirelyBeforePosition); @@ -10257,11 +9419,11 @@ namespace IncrementalParser { return bestResult; - function getLastDescendant(node: Node): Node { + function getLastDescendant(node: AstNode): AstNode { while (true) { - const lastChild = getLastChild(node); + const lastChild = getLastChild(node.node); // TODO(rbuckton): do not instantiate .node if (lastChild) { - node = lastChild; + node = (lastChild as AstNode["node"]).ast; } else { return node; @@ -10269,7 +9431,11 @@ namespace IncrementalParser { } } - function visit(child: Node) { + function visit(child: Node | AstNode) { + if (!(child instanceof AstNode)) { + child = (child as AstNode["node"]).ast; + } + if (nodeIsMissing(child)) { // Missing nodes are effectively invisible to us. We never even consider them // When trying to find the nearest node before us. @@ -10293,7 +9459,7 @@ namespace IncrementalParser { // The nearest node is either this child, or one of the children inside // of it. We've already marked this child as the best so far. Recurse // in case one of the children is better. - forEachChild(child, visit); + forEachChild(child.node, visit); // TODO(rbuckton): do not instantiate .node // Once we look at the children of this node, then there's no need to // continue any further. @@ -10327,8 +9493,8 @@ namespace IncrementalParser { } } - function checkChangeRange(sourceFile: SourceFile, newText: string, textChangeRange: TextChangeRange, aggressiveChecks: boolean) { - const oldText = sourceFile.text; + function checkChangeRange(sourceFile: AstSourceFile, newText: string, textChangeRange: TextChangeRange, aggressiveChecks: boolean) { + const oldText = sourceFile.data.text; if (textChangeRange) { Debug.assert((oldText.length - textChangeRange.span.length + textChangeRange.newLength) === newText.length); @@ -10348,15 +9514,15 @@ namespace IncrementalParser { // The implementation takes advantage of the calling pattern it knows the parser will // make in order to optimize finding nodes as quickly as possible. export interface SyntaxCursor { - currentNode(position: number): Node; + currentNode(position: number): AstNode; } - export function createSyntaxCursor(sourceFile: SourceFile): SyntaxCursor { - let currentArray: NodeArray = sourceFile.statements; + export function createSyntaxCursor(sourceFile: AstSourceFile): SyntaxCursor { + let currentArray: AstNodeArray = sourceFile.data.statements; let currentArrayIndex = 0; - Debug.assert(currentArrayIndex < currentArray.length); - let current = currentArray[currentArrayIndex]; + Debug.assert(currentArrayIndex < currentArray.items.length); + let current = currentArray.items[currentArrayIndex]; let lastQueriedPosition = InvalidPosition.Value; return { @@ -10369,9 +9535,9 @@ namespace IncrementalParser { // Much of the time the parser will need the very next node in the array that // we just returned a node from.So just simply check for that case and move // forward in the array instead of searching for the node again. - if (current && current.end === position && currentArrayIndex < (currentArray.length - 1)) { + if (current && current.end === position && currentArrayIndex < (currentArray.items.length - 1)) { currentArrayIndex++; - current = currentArray[currentArrayIndex]; + current = currentArray.items[currentArrayIndex]; } // If we don't have a node, or the node we have isn't in the right position, @@ -10404,10 +9570,10 @@ namespace IncrementalParser { current = undefined!; // Recurse into the source file to find the highest node at this position. - forEachChild(sourceFile, visitNode, visitArray); + forEachChild(sourceFile.node, visitNode, visitArray); // TODO(rbuckton): do not instantiate .node return; - function visitNode(node: Node) { + function visitNode(node: Node) { // TODO(rbuckton): use AstNode if (position >= node.pos && position < node.end) { // Position was within this node. Keep searching deeper to find the node. forEachChild(node, visitNode, visitArray); @@ -10420,12 +9586,16 @@ namespace IncrementalParser { return false; } - function visitArray(array: NodeArray) { + function visitArray(array: NodeArray | AstNodeArray) { + if (!(array instanceof AstNodeArray)) { + array = (array as AstNodeArray["nodes"]).ast; + } + if (position >= array.pos && position < array.end) { // position was in this array. Search through this array to see if we find a // viable element. - for (let i = 0; i < array.length; i++) { - const child = array[i]; + for (let i = 0; i < array.items.length; i++) { + const child = array.items[i]; if (child) { if (child.pos === position) { // Found the right node. We're done. @@ -10438,7 +9608,7 @@ namespace IncrementalParser { if (child.pos < position && position < child.end) { // Position in somewhere within this child. Search in it and // stop searching in this array. - forEachChild(child, visitNode, visitArray); + forEachChild(child.node, visitNode, visitArray); // TODO(rbuckton): do not instantiate .node return true; } } @@ -10702,13 +9872,15 @@ function getNamedPragmaArguments(pragma: PragmaDefinition, text: string | undefi } /** @internal */ -export function tagNamesAreEquivalent(lhs: JsxTagNameExpression, rhs: JsxTagNameExpression): boolean { +export function tagNamesAreEquivalent(lhs: JsxTagNameExpression | ast.AstJsxTagNameExpression, rhs: JsxTagNameExpression | ast.AstJsxTagNameExpression): boolean { + if (!(lhs instanceof AstNode)) lhs = (lhs as AstJsxTagNameExpression["node"]).ast; + if (!(rhs instanceof AstNode)) rhs = (rhs as AstJsxTagNameExpression["node"]).ast; if (lhs.kind !== rhs.kind) { return false; } if (lhs.kind === SyntaxKind.Identifier) { - return lhs.escapedText === (rhs as Identifier).escapedText; + return lhs.data.escapedText === (rhs as AstIdentifier).data.escapedText; } if (lhs.kind === SyntaxKind.ThisKeyword) { @@ -10716,13 +9888,13 @@ export function tagNamesAreEquivalent(lhs: JsxTagNameExpression, rhs: JsxTagName } if (lhs.kind === SyntaxKind.JsxNamespacedName) { - return lhs.namespace.escapedText === (rhs as JsxNamespacedName).namespace.escapedText && - lhs.name.escapedText === (rhs as JsxNamespacedName).name.escapedText; + return lhs.data.namespace.data.escapedText === (rhs as AstJsxNamespacedName).data.namespace.data.escapedText && + lhs.data.name.data.escapedText === (rhs as AstJsxNamespacedName).data.name.data.escapedText; } // If we are at this statement then we must have PropertyAccessExpression and because tag name in Jsx element can only // take forms of JsxTagNameExpression which includes an identifier, "this" expression, or another propertyAccessExpression // it is safe to case the expression property as such. See parseJsxElementName for how we parse tag name in Jsx element - return (lhs as PropertyAccessExpression).name.escapedText === (rhs as PropertyAccessExpression).name.escapedText && - tagNamesAreEquivalent((lhs as PropertyAccessExpression).expression as JsxTagNameExpression, (rhs as PropertyAccessExpression).expression as JsxTagNameExpression); + return (lhs as AstPropertyAccessExpression).data.name.data.escapedText === (rhs as AstPropertyAccessExpression).data.name.data.escapedText && + tagNamesAreEquivalent((lhs as AstPropertyAccessExpression).data.expression as AstJsxTagNameExpression, (rhs as AstPropertyAccessExpression).data.expression as AstJsxTagNameExpression); } diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index 709211b797d..1ebfe3837a4 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -777,7 +777,7 @@ export function usingSingleLineStringWriter(action: (writer: EmitTextWriter) => } /** @internal */ -export function getFullWidth(node: Node): number { +export function getFullWidth(node: Node | ast.AstNode): number { return node.end - node.pos; } @@ -933,8 +933,8 @@ export function hasChangesInResolutions( // Returns true if this node contains a parse error anywhere underneath it. /** @internal */ -export function containsParseError(node: Node): boolean { - aggregateChildData(node); +export function containsParseError(node: Node | ast.AstNode): boolean { + aggregateChildData(node instanceof ast.AstNode ? node.node : node); // TODO(rbuckton): do not instantiate node return (node.flags & NodeFlags.ThisNodeOrAnySubNodesHasError) !== 0; } @@ -1058,7 +1058,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 | undefined): boolean { +export function nodeIsMissing(node: Node | ast.AstNode | undefined): boolean { if (node === undefined) { return true; } @@ -1067,7 +1067,7 @@ export function nodeIsMissing(node: Node | undefined): boolean { } /** @internal */ -export function nodeIsPresent(node: Node | undefined): boolean { +export function nodeIsPresent(node: Node | ast.AstNode | undefined): boolean { return !nodeIsMissing(node); } @@ -1279,8 +1279,10 @@ export function getSourceTextOfNodeFromSourceFile(sourceFile: SourceFile, node: return getTextOfNodeFromSourceText(sourceFile.text, node, includeTrivia); } -function isJSDocTypeExpressionOrChild(node: Node): boolean { - return !!findAncestor(node, isJSDocTypeExpression); +function isJSDocTypeExpressionOrChild(node: Node | ast.AstNode): boolean { + return node instanceof ast.AstNode ? + !!findAncestor(node, ast.isAstJSDocTypeExpression) : + !!findAncestor(node, isJSDocTypeExpression); } /** @internal */ @@ -1310,7 +1312,7 @@ export function moduleExportNameIsDefault(node: ModuleExportName): boolean { } /** @internal */ -export function getTextOfNodeFromSourceText(sourceText: string, node: Node, includeTrivia = false): string { +export function getTextOfNodeFromSourceText(sourceText: string, node: Node | ast.AstNode, includeTrivia = false): string { if (nodeIsMissing(node)) { return ""; } @@ -2608,7 +2610,7 @@ export function getLeadingCommentRangesOfNode(node: Node, sourceFileOfNode: Sour } /** @internal */ -export function getJSDocCommentRanges(node: Node, text: string): CommentRange[] | undefined { +export function getJSDocCommentRanges(node: Node | ast.AstNode, text: string): CommentRange[] | undefined { const commentRanges = (node.kind === SyntaxKind.Parameter || node.kind === SyntaxKind.TypeParameter || node.kind === SyntaxKind.FunctionExpression || @@ -4390,7 +4392,10 @@ export function canHaveFlowNode(node: Node): node is HasFlowNode { } /** @internal */ -export function canHaveJSDoc(node: Node): node is HasJSDoc { +export function canHaveJSDoc(node: Node): node is HasJSDoc; +/** @internal */ +export function canHaveJSDoc(node: ast.AstNode): node is ast.AstHasJSDoc; +export function canHaveJSDoc(node: Node | ast.AstNode) { switch (node.kind) { case SyntaxKind.ArrowFunction: case SyntaxKind.BinaryExpression: @@ -7167,7 +7172,7 @@ export function getSyntacticModifierFlagsNoCache(node: Node): ModifierFlags { } /** @internal */ -export function modifiersToFlags(modifiers: readonly ModifierLike[] | undefined): ModifierFlags { +export function modifiersToFlags(modifiers: readonly ModifierLike[] | readonly ast.AstModifierLike[] | undefined): ModifierFlags { let flags = ModifierFlags.None; if (modifiers) { for (const modifier of modifiers) { @@ -10419,11 +10424,11 @@ export function setNodeFlags(node: T | undefined, newFlags: Node * * @internal */ -export function setParent(child: T, parent: T["parent"] | undefined): T; +export function setParent(child: T, parent: T["parent"] | undefined): T; /** @internal */ -export function setParent(child: T | undefined, parent: T["parent"] | undefined): T | undefined; +export function setParent(child: T | undefined, parent: T["parent"] | undefined): T | undefined; /** @internal */ -export function setParent(child: T | undefined, parent: T["parent"] | undefined): T | undefined { +export function setParent(child: T | undefined, parent: T["parent"] | undefined): T | undefined { if (child && parent) { (child as Mutable).parent = parent; } diff --git a/src/compiler/utilitiesPublic.ts b/src/compiler/utilitiesPublic.ts index 41c8549cc80..3608fbada22 100644 --- a/src/compiler/utilitiesPublic.ts +++ b/src/compiler/utilitiesPublic.ts @@ -769,6 +769,18 @@ export function getOriginalNode(node: Node | undefined, nodeTest return nodeTest(node) ? node : undefined; } +interface AncestorTraversable> { + parent: T | undefined; +} + +/** + * Iterates through the parent chain of a node and performs the callback on each parent until the callback + * returns a truthy value, then returns that value. + * If no such value is found, it applies the callback until the parent pointer is undefined or the callback returns "quit" + * At that point findAncestor returns undefined. + * @internal + */ +export function findAncestor(node: ast.AstNode | undefined, callback: (element: ast.AstNode) => element is T): T | undefined; /** * Iterates through the parent chain of a node and performs the callback on each parent until the callback * returns a truthy value, then returns that value. @@ -776,8 +788,10 @@ export function getOriginalNode(node: Node | undefined, nodeTest * At that point findAncestor returns undefined. */ export function findAncestor(node: Node | undefined, callback: (element: Node) => element is T): T | undefined; +/** @internal */ +export function findAncestor(node: ast.AstNode | undefined, callback: (element: ast.AstNode) => boolean | "quit"): ast.AstNode | undefined; export function findAncestor(node: Node | undefined, callback: (element: Node) => boolean | "quit"): Node | undefined; -export function findAncestor(node: Node | undefined, callback: (element: Node) => boolean | "quit"): Node | undefined { +export function findAncestor>(node: T | T | undefined, callback: (element: T) => boolean | "quit"): T | undefined { while (node) { const result = callback(node); if (result === "quit") {