• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1namespace ts {
2    const enum SignatureFlags {
3        None = 0,
4        Yield = 1 << 0,
5        Await = 1 << 1,
6        Type  = 1 << 2,
7        IgnoreMissingOpenBrace = 1 << 4,
8        JSDoc = 1 << 5,
9    }
10
11    const enum SpeculationKind {
12        TryParse,
13        Lookahead,
14        Reparse
15    }
16
17    let NodeConstructor: new (kind: SyntaxKind, pos?: number, end?: number) => Node;
18    let TokenConstructor: new (kind: SyntaxKind, pos?: number, end?: number) => Node;
19    let IdentifierConstructor: new (kind: SyntaxKind, pos?: number, end?: number) => Node;
20    let PrivateIdentifierConstructor: new (kind: SyntaxKind, pos?: number, end?: number) => Node;
21    let SourceFileConstructor: new (kind: SyntaxKind, pos?: number, end?: number) => Node;
22
23    /**
24     * NOTE: You should not use this, it is only exported to support `createNode` in `~/src/deprecatedCompat/deprecations.ts`.
25     */
26    /* @internal */
27    export const parseBaseNodeFactory: BaseNodeFactory = {
28        createBaseSourceFileNode: kind => new (SourceFileConstructor || (SourceFileConstructor = objectAllocator.getSourceFileConstructor()))(kind, -1, -1),
29        createBaseIdentifierNode: kind => new (IdentifierConstructor || (IdentifierConstructor = objectAllocator.getIdentifierConstructor()))(kind, -1, -1),
30        createBasePrivateIdentifierNode: kind => new (PrivateIdentifierConstructor || (PrivateIdentifierConstructor = objectAllocator.getPrivateIdentifierConstructor()))(kind, -1, -1),
31        createBaseTokenNode: kind => new (TokenConstructor || (TokenConstructor = objectAllocator.getTokenConstructor()))(kind, -1, -1),
32        createBaseNode: kind => new (NodeConstructor || (NodeConstructor = objectAllocator.getNodeConstructor()))(kind, -1, -1),
33    };
34
35    /* @internal */
36    export const parseNodeFactory = createNodeFactory(NodeFactoryFlags.NoParenthesizerRules, parseBaseNodeFactory);
37
38    function visitNode<T>(cbNode: (node: Node) => T, node: Node | undefined): T | undefined {
39        return node && cbNode(node);
40    }
41
42    function visitNodes<T>(cbNode: (node: Node) => T, cbNodes: ((node: NodeArray<Node>) => T | undefined) | undefined, nodes: NodeArray<Node> | undefined): T | undefined {
43        if (nodes) {
44            if (cbNodes) {
45                return cbNodes(nodes);
46            }
47            for (const node of nodes) {
48                const result = cbNode(node);
49                if (result) {
50                    return result;
51                }
52            }
53        }
54    }
55
56    /*@internal*/
57    export function isJSDocLikeText(text: string, start: number) {
58        return text.charCodeAt(start + 1) === CharacterCodes.asterisk &&
59            text.charCodeAt(start + 2) === CharacterCodes.asterisk &&
60            text.charCodeAt(start + 3) !== CharacterCodes.slash;
61    }
62
63    /*@internal*/
64    export function isFileProbablyExternalModule(sourceFile: SourceFile) {
65        // Try to use the first top-level import/export when available, then
66        // fall back to looking for an 'import.meta' somewhere in the tree if necessary.
67        return forEach(sourceFile.statements, isAnExternalModuleIndicatorNode) ||
68            getImportMetaIfNecessary(sourceFile);
69    }
70
71    function isAnExternalModuleIndicatorNode(node: Node) {
72        return canHaveModifiers(node) && hasModifierOfKind(node, SyntaxKind.ExportKeyword)
73            || isImportEqualsDeclaration(node) && isExternalModuleReference(node.moduleReference)
74            || isImportDeclaration(node)
75            || isExportAssignment(node)
76            || isExportDeclaration(node) ? node : undefined;
77    }
78
79    function getImportMetaIfNecessary(sourceFile: SourceFile) {
80        return sourceFile.flags & NodeFlags.PossiblyContainsImportMeta ?
81            walkTreeForImportMeta(sourceFile) :
82            undefined;
83    }
84
85    function walkTreeForImportMeta(node: Node): Node | undefined {
86        return isImportMeta(node) ? node : forEachChild(node, walkTreeForImportMeta);
87    }
88
89    /** Do not use hasModifier inside the parser; it relies on parent pointers. Use this instead. */
90    function hasModifierOfKind(node: HasModifiers, kind: SyntaxKind) {
91        return some(node.modifiers, m => m.kind === kind);
92    }
93
94    function isImportMeta(node: Node): boolean {
95        return isMetaProperty(node) && node.keywordToken === SyntaxKind.ImportKeyword && node.name.escapedText === "meta";
96    }
97
98    type ForEachChildFunction<TNode> = <T>(node: TNode, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray<Node>) => T | undefined) => T | undefined;
99    type ForEachChildTable = { [TNode in ForEachChildNodes as TNode["kind"]]: ForEachChildFunction<TNode> };
100    const forEachChildTable: ForEachChildTable = {
101        [SyntaxKind.QualifiedName]: function forEachChildInQualifiedName<T>(node: QualifiedName, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray<Node>) => T | undefined): T | undefined {
102            return visitNode(cbNode, node.left) ||
103                visitNode(cbNode, node.right);
104        },
105        [SyntaxKind.TypeParameter]: function forEachChildInTypeParameter<T>(node: TypeParameterDeclaration, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray<Node>) => T | undefined): T | undefined {
106            return visitNodes(cbNode, cbNodes, node.modifiers) ||
107                visitNode(cbNode, node.name) ||
108                visitNode(cbNode, node.constraint) ||
109                visitNode(cbNode, node.default) ||
110                visitNode(cbNode, node.expression);
111        },
112        [SyntaxKind.ShorthandPropertyAssignment]: function forEachChildInShorthandPropertyAssignment<T>(node: ShorthandPropertyAssignment, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray<Node>) => T | undefined): T | undefined {
113            return visitNodes(cbNode, cbNodes, node.illegalDecorators) ||
114                visitNodes(cbNode, cbNodes, node.modifiers) ||
115                visitNode(cbNode, node.name) ||
116                visitNode(cbNode, node.questionToken) ||
117                visitNode(cbNode, node.exclamationToken) ||
118                visitNode(cbNode, node.equalsToken) ||
119                visitNode(cbNode, node.objectAssignmentInitializer);
120        },
121        [SyntaxKind.SpreadAssignment]: function forEachChildInSpreadAssignment<T>(node: SpreadAssignment, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray<Node>) => T | undefined): T | undefined {
122            return visitNode(cbNode, node.expression);
123        },
124        [SyntaxKind.Parameter]: function forEachChildInParameter<T>(node: ParameterDeclaration, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray<Node>) => T | undefined): T | undefined {
125            return visitNodes(cbNode, cbNodes, node.modifiers) ||
126                visitNode(cbNode, node.dotDotDotToken) ||
127                visitNode(cbNode, node.name) ||
128                visitNode(cbNode, node.questionToken) ||
129                visitNode(cbNode, node.type) ||
130                visitNode(cbNode, node.initializer);
131        },
132        [SyntaxKind.PropertyDeclaration]: function forEachChildInPropertyDeclaration<T>(node: PropertyDeclaration, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray<Node>) => T | undefined): T | undefined {
133            return visitNodes(cbNode, cbNodes, node.modifiers) ||
134                visitNode(cbNode, node.name) ||
135                visitNode(cbNode, node.questionToken) ||
136                visitNode(cbNode, node.exclamationToken) ||
137                visitNode(cbNode, node.type) ||
138                visitNode(cbNode, node.initializer);
139        },
140        [SyntaxKind.AnnotationPropertyDeclaration]: function forEachChildInAnnotationPropertyDeclaration<T>(node: AnnotationPropertyDeclaration, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray<Node>) => T | undefined): T | undefined {
141            return visitNode(cbNode, node.name) ||
142                visitNode(cbNode, node.type) ||
143                visitNode(cbNode, node.initializer);
144        },
145        [SyntaxKind.PropertySignature]: function forEachChildInPropertySignature<T>(node: PropertySignature, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray<Node>) => T | undefined): T | undefined {
146            return visitNodes(cbNode, cbNodes, node.modifiers) ||
147                visitNode(cbNode, node.name) ||
148                visitNode(cbNode, node.questionToken) ||
149                visitNode(cbNode, node.type) ||
150                visitNode(cbNode, node.initializer);
151        },
152        [SyntaxKind.PropertyAssignment]: function forEachChildInPropertyAssignment<T>(node: PropertyAssignment, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray<Node>) => T | undefined): T | undefined {
153            return visitNodes(cbNode, cbNodes, node.illegalDecorators) ||
154                visitNodes(cbNode, cbNodes, node.modifiers) ||
155                visitNode(cbNode, node.name) ||
156                visitNode(cbNode, node.questionToken) ||
157                visitNode(cbNode, node.exclamationToken) ||
158                visitNode(cbNode, node.initializer);
159        },
160        [SyntaxKind.VariableDeclaration]: function forEachChildInVariableDeclaration<T>(node: VariableDeclaration, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray<Node>) => T | undefined): T | undefined {
161            return visitNode(cbNode, node.name) ||
162                visitNode(cbNode, node.exclamationToken) ||
163                visitNode(cbNode, node.type) ||
164                visitNode(cbNode, node.initializer);
165        },
166        [SyntaxKind.BindingElement]: function forEachChildInBindingElement<T>(node: BindingElement, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray<Node>) => T | undefined): T | undefined {
167            return visitNode(cbNode, node.dotDotDotToken) ||
168                visitNode(cbNode, node.propertyName) ||
169                visitNode(cbNode, node.name) ||
170                visitNode(cbNode, node.initializer);
171        },
172        [SyntaxKind.IndexSignature]: function forEachChildInIndexSignature<T>(node: IndexSignatureDeclaration, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray<Node>) => T | undefined): T | undefined {
173            return visitNodes(cbNode, cbNodes, node.illegalDecorators) ||
174                visitNodes(cbNode, cbNodes, node.modifiers) ||
175                visitNodes(cbNode, cbNodes, node.typeParameters) ||
176                visitNodes(cbNode, cbNodes, node.parameters) ||
177                visitNode(cbNode, node.type);
178        },
179        [SyntaxKind.ConstructorType]: function forEachChildInConstructorType<T>(node: ConstructorTypeNode, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray<Node>) => T | undefined): T | undefined {
180            return visitNodes(cbNode, cbNodes, node.modifiers) ||
181                visitNodes(cbNode, cbNodes, node.typeParameters) ||
182                visitNodes(cbNode, cbNodes, node.parameters) ||
183                visitNode(cbNode, node.type);
184        },
185        [SyntaxKind.FunctionType]: function forEachChildInFunctionType<T>(node: FunctionTypeNode, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray<Node>) => T | undefined): T | undefined {
186            return visitNodes(cbNode, cbNodes, node.modifiers) ||
187                visitNodes(cbNode, cbNodes, node.typeParameters) ||
188                visitNodes(cbNode, cbNodes, node.parameters) ||
189                visitNode(cbNode, node.type);
190        },
191        [SyntaxKind.CallSignature]: forEachChildInCallOrConstructSignature,
192        [SyntaxKind.ConstructSignature]: forEachChildInCallOrConstructSignature,
193        [SyntaxKind.EtsComponentExpression]: function forEachChildInEtsComponentExpression<T>(node: EtsComponentExpression, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray<Node>) => T | undefined): T | undefined {
194            return visitNode(cbNode, node.expression) ||
195              visitNodes(cbNode, cbNodes, node.arguments) ||
196              visitNode(cbNode, node.body);
197        },
198        [SyntaxKind.MethodDeclaration]: function forEachChildInMethodDeclaration<T>(node: MethodDeclaration, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray<Node>) => T | undefined): T | undefined {
199            return visitNodes(cbNode, cbNodes, node.modifiers) ||
200                visitNode(cbNode, node.asteriskToken) ||
201                visitNode(cbNode, node.name) ||
202                visitNode(cbNode, node.questionToken) ||
203                visitNode(cbNode, node.exclamationToken) ||
204                visitNodes(cbNode, cbNodes, node.typeParameters) ||
205                visitNodes(cbNode, cbNodes, node.parameters) ||
206                visitNode(cbNode, node.type) ||
207                visitNode(cbNode, node.body);
208        },
209        [SyntaxKind.MethodSignature]: function forEachChildInMethodSignature<T>(node: MethodSignature, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray<Node>) => T | undefined): T | undefined {
210            return visitNodes(cbNode, cbNodes, node.modifiers) ||
211                visitNode(cbNode, node.name) ||
212                visitNode(cbNode, node.questionToken) ||
213                visitNodes(cbNode, cbNodes, node.typeParameters) ||
214                visitNodes(cbNode, cbNodes, node.parameters) ||
215                visitNode(cbNode, node.type);
216        },
217        [SyntaxKind.Constructor]: function forEachChildInConstructor<T>(node: ConstructorDeclaration, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray<Node>) => T | undefined): T | undefined {
218            return visitNodes(cbNode, cbNodes, node.illegalDecorators) ||
219                visitNodes(cbNode, cbNodes, node.modifiers) ||
220                visitNode(cbNode, node.name) ||
221                visitNodes(cbNode, cbNodes, node.typeParameters) ||
222                visitNodes(cbNode, cbNodes, node.parameters) ||
223                visitNode(cbNode, node.type) ||
224                visitNode(cbNode, node.body);
225        },
226        [SyntaxKind.GetAccessor]: function forEachChildInGetAccessor<T>(node: GetAccessorDeclaration, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray<Node>) => T | undefined): T | undefined {
227            return visitNodes(cbNode, cbNodes, node.modifiers) ||
228                visitNode(cbNode, node.name) ||
229                visitNodes(cbNode, cbNodes, node.typeParameters) ||
230                visitNodes(cbNode, cbNodes, node.parameters) ||
231                visitNode(cbNode, node.type) ||
232                visitNode(cbNode, node.body);
233        },
234        [SyntaxKind.SetAccessor]: function forEachChildInSetAccessor<T>(node: SetAccessorDeclaration, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray<Node>) => T | undefined): T | undefined {
235            return visitNodes(cbNode, cbNodes, node.modifiers) ||
236                visitNode(cbNode, node.name) ||
237                visitNodes(cbNode, cbNodes, node.typeParameters) ||
238                visitNodes(cbNode, cbNodes, node.parameters) ||
239                visitNode(cbNode, node.type) ||
240                visitNode(cbNode, node.body);
241        },
242        [SyntaxKind.FunctionDeclaration]: function forEachChildInFunctionDeclaration<T>(node: FunctionDeclaration, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray<Node>) => T | undefined): T | undefined {
243            return visitNodes(cbNode, cbNodes, node.illegalDecorators) ||
244                visitNodes(cbNode, cbNodes, node.modifiers) ||
245                visitNode(cbNode, node.asteriskToken) ||
246                visitNode(cbNode, node.name) ||
247                visitNodes(cbNode, cbNodes, node.typeParameters) ||
248                visitNodes(cbNode, cbNodes, node.parameters) ||
249                visitNode(cbNode, node.type) ||
250                visitNode(cbNode, node.body);
251        },
252        [SyntaxKind.FunctionExpression]: function forEachChildInFunctionExpression<T>(node: FunctionExpression, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray<Node>) => T | undefined): T | undefined {
253            return visitNodes(cbNode, cbNodes, node.modifiers) ||
254                visitNode(cbNode, node.asteriskToken) ||
255                visitNode(cbNode, node.name) ||
256                visitNodes(cbNode, cbNodes, node.typeParameters) ||
257                visitNodes(cbNode, cbNodes, node.parameters) ||
258                visitNode(cbNode, node.type) ||
259                visitNode(cbNode, node.body);
260        },
261        [SyntaxKind.ArrowFunction]: function forEachChildInArrowFunction<T>(node: ArrowFunction, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray<Node>) => T | undefined): T | undefined {
262            return visitNodes(cbNode, cbNodes, node.modifiers) ||
263                visitNodes(cbNode, cbNodes, node.typeParameters) ||
264                visitNodes(cbNode, cbNodes, node.parameters) ||
265                visitNode(cbNode, node.type) ||
266                visitNode(cbNode, node.equalsGreaterThanToken) ||
267                visitNode(cbNode, node.body);
268        },
269        [SyntaxKind.ClassStaticBlockDeclaration]: function forEachChildInClassStaticBlockDeclaration<T>(node: ClassStaticBlockDeclaration, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray<Node>) => T | undefined): T | undefined {
270            return visitNodes(cbNode, cbNodes, node.illegalDecorators) ||
271                visitNodes(cbNode, cbNodes, node.modifiers) ||
272                visitNode(cbNode, node.body);
273        },
274        [SyntaxKind.TypeReference]: function forEachChildInTypeReference<T>(node: TypeReferenceNode, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray<Node>) => T | undefined): T | undefined {
275            return visitNode(cbNode, node.typeName) ||
276                visitNodes(cbNode, cbNodes, node.typeArguments);
277        },
278        [SyntaxKind.TypePredicate]: function forEachChildInTypePredicate<T>(node: TypePredicateNode, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray<Node>) => T | undefined): T | undefined {
279            return visitNode(cbNode, node.assertsModifier) ||
280                visitNode(cbNode, node.parameterName) ||
281                visitNode(cbNode, node.type);
282        },
283        [SyntaxKind.TypeQuery]: function forEachChildInTypeQuery<T>(node: TypeQueryNode, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray<Node>) => T | undefined): T | undefined {
284            return visitNode(cbNode, node.exprName) ||
285                visitNodes(cbNode, cbNodes, node.typeArguments);
286        },
287        [SyntaxKind.TypeLiteral]: function forEachChildInTypeLiteral<T>(node: TypeLiteralNode, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray<Node>) => T | undefined): T | undefined {
288            return visitNodes(cbNode, cbNodes, node.members);
289        },
290        [SyntaxKind.ArrayType]: function forEachChildInArrayType<T>(node: ArrayTypeNode, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray<Node>) => T | undefined): T | undefined {
291            return visitNode(cbNode, node.elementType);
292        },
293        [SyntaxKind.TupleType]: function forEachChildInTupleType<T>(node: TupleTypeNode, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray<Node>) => T | undefined): T | undefined {
294            return visitNodes(cbNode, cbNodes, node.elements);
295        },
296        [SyntaxKind.UnionType]: forEachChildInUnionOrIntersectionType,
297        [SyntaxKind.IntersectionType]: forEachChildInUnionOrIntersectionType,
298        [SyntaxKind.ConditionalType]: function forEachChildInConditionalType<T>(node: ConditionalTypeNode, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray<Node>) => T | undefined): T | undefined {
299            return visitNode(cbNode, node.checkType) ||
300                visitNode(cbNode, node.extendsType) ||
301                visitNode(cbNode, node.trueType) ||
302                visitNode(cbNode, node.falseType);
303        },
304        [SyntaxKind.InferType]: function forEachChildInInferType<T>(node: InferTypeNode, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray<Node>) => T | undefined): T | undefined {
305            return visitNode(cbNode, node.typeParameter);
306        },
307        [SyntaxKind.ImportType]: function forEachChildInImportType<T>(node: ImportTypeNode, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray<Node>) => T | undefined): T | undefined {
308            return visitNode(cbNode, node.argument) ||
309                visitNode(cbNode, node.assertions) ||
310                visitNode(cbNode, node.qualifier) ||
311                visitNodes(cbNode, cbNodes, node.typeArguments);
312        },
313        [SyntaxKind.ImportTypeAssertionContainer]: function forEachChildInImportTypeAssertionContainer<T>(node: ImportTypeAssertionContainer, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray<Node>) => T | undefined): T | undefined {
314            return visitNode(cbNode, node.assertClause);
315        },
316        [SyntaxKind.ParenthesizedType]: forEachChildInParenthesizedTypeOrTypeOperator,
317        [SyntaxKind.TypeOperator]: forEachChildInParenthesizedTypeOrTypeOperator,
318        [SyntaxKind.IndexedAccessType]: function forEachChildInIndexedAccessType<T>(node: IndexedAccessTypeNode, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray<Node>) => T | undefined): T | undefined {
319            return visitNode(cbNode, node.objectType) ||
320                visitNode(cbNode, node.indexType);
321        },
322        [SyntaxKind.MappedType]: function forEachChildInMappedType<T>(node: MappedTypeNode, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray<Node>) => T | undefined): T | undefined {
323            return visitNode(cbNode, node.readonlyToken) ||
324                visitNode(cbNode, node.typeParameter) ||
325                visitNode(cbNode, node.nameType) ||
326                visitNode(cbNode, node.questionToken) ||
327                visitNode(cbNode, node.type) ||
328                visitNodes(cbNode, cbNodes, node.members);
329        },
330        [SyntaxKind.LiteralType]: function forEachChildInLiteralType<T>(node: LiteralTypeNode, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray<Node>) => T | undefined): T | undefined {
331            return visitNode(cbNode, node.literal);
332        },
333        [SyntaxKind.NamedTupleMember]: function forEachChildInNamedTupleMember<T>(node: NamedTupleMember, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray<Node>) => T | undefined): T | undefined {
334            return visitNode(cbNode, node.dotDotDotToken) ||
335                visitNode(cbNode, node.name) ||
336                visitNode(cbNode, node.questionToken) ||
337                visitNode(cbNode, node.type);
338        },
339        [SyntaxKind.ObjectBindingPattern]: forEachChildInObjectOrArrayBindingPattern,
340        [SyntaxKind.ArrayBindingPattern]: forEachChildInObjectOrArrayBindingPattern,
341        [SyntaxKind.ArrayLiteralExpression]: function forEachChildInArrayLiteralExpression<T>(node: ArrayLiteralExpression, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray<Node>) => T | undefined): T | undefined {
342            return visitNodes(cbNode, cbNodes, node.elements);
343        },
344        [SyntaxKind.ObjectLiteralExpression]: function forEachChildInObjectLiteralExpression<T>(node: ObjectLiteralExpression, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray<Node>) => T | undefined): T | undefined {
345            return visitNodes(cbNode, cbNodes, node.properties);
346        },
347        [SyntaxKind.PropertyAccessExpression]: function forEachChildInPropertyAccessExpression<T>(node: PropertyAccessExpression, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray<Node>) => T | undefined): T | undefined {
348            return visitNode(cbNode, node.expression) ||
349                visitNode(cbNode, node.questionDotToken) ||
350                visitNode(cbNode, node.name);
351        },
352        [SyntaxKind.ElementAccessExpression]: function forEachChildInElementAccessExpression<T>(node: ElementAccessExpression, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray<Node>) => T | undefined): T | undefined {
353            return visitNode(cbNode, node.expression) ||
354                visitNode(cbNode, node.questionDotToken) ||
355                visitNode(cbNode, node.argumentExpression);
356        },
357        [SyntaxKind.CallExpression]: forEachChildInCallOrNewExpression,
358        [SyntaxKind.NewExpression]: forEachChildInCallOrNewExpression,
359        [SyntaxKind.TaggedTemplateExpression]: function forEachChildInTaggedTemplateExpression<T>(node: TaggedTemplateExpression, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray<Node>) => T | undefined): T | undefined {
360            return visitNode(cbNode, node.tag) ||
361                visitNode(cbNode, node.questionDotToken) ||
362                visitNodes(cbNode, cbNodes, node.typeArguments) ||
363                visitNode(cbNode, node.template);
364        },
365        [SyntaxKind.TypeAssertionExpression]: function forEachChildInTypeAssertionExpression<T>(node: TypeAssertion, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray<Node>) => T | undefined): T | undefined {
366            return visitNode(cbNode, node.type) ||
367                visitNode(cbNode, node.expression);
368        },
369        [SyntaxKind.ParenthesizedExpression]: function forEachChildInParenthesizedExpression<T>(node: ParenthesizedExpression, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray<Node>) => T | undefined): T | undefined {
370            return visitNode(cbNode, node.expression);
371        },
372        [SyntaxKind.DeleteExpression]: function forEachChildInDeleteExpression<T>(node: DeleteExpression, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray<Node>) => T | undefined): T | undefined {
373            return visitNode(cbNode, node.expression);
374        },
375        [SyntaxKind.TypeOfExpression]: function forEachChildInTypeOfExpression<T>(node: TypeOfExpression, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray<Node>) => T | undefined): T | undefined {
376            return visitNode(cbNode, node.expression);
377        },
378        [SyntaxKind.VoidExpression]: function forEachChildInVoidExpression<T>(node: VoidExpression, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray<Node>) => T | undefined): T | undefined {
379            return visitNode(cbNode, node.expression);
380        },
381        [SyntaxKind.PrefixUnaryExpression]: function forEachChildInPrefixUnaryExpression<T>(node: PrefixUnaryExpression, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray<Node>) => T | undefined): T | undefined {
382            return visitNode(cbNode, node.operand);
383        },
384        [SyntaxKind.YieldExpression]: function forEachChildInYieldExpression<T>(node: YieldExpression, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray<Node>) => T | undefined): T | undefined {
385            return visitNode(cbNode, node.asteriskToken) ||
386                visitNode(cbNode, node.expression);
387        },
388        [SyntaxKind.AwaitExpression]: function forEachChildInAwaitExpression<T>(node: AwaitExpression, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray<Node>) => T | undefined): T | undefined {
389            return visitNode(cbNode, node.expression);
390        },
391        [SyntaxKind.PostfixUnaryExpression]: function forEachChildInPostfixUnaryExpression<T>(node: PostfixUnaryExpression, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray<Node>) => T | undefined): T | undefined {
392            return visitNode(cbNode, node.operand);
393        },
394        [SyntaxKind.BinaryExpression]: function forEachChildInBinaryExpression<T>(node: BinaryExpression, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray<Node>) => T | undefined): T | undefined {
395            return visitNode(cbNode, node.left) ||
396                visitNode(cbNode, node.operatorToken) ||
397                visitNode(cbNode, node.right);
398        },
399        [SyntaxKind.AsExpression]: function forEachChildInAsExpression<T>(node: AsExpression, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray<Node>) => T | undefined): T | undefined {
400            return visitNode(cbNode, node.expression) ||
401                visitNode(cbNode, node.type);
402        },
403        [SyntaxKind.NonNullExpression]: function forEachChildInNonNullExpression<T>(node: NonNullExpression, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray<Node>) => T | undefined): T | undefined {
404            return visitNode(cbNode, node.expression);
405        },
406        [SyntaxKind.SatisfiesExpression]: function forEachChildInSatisfiesExpression<T>(node: SatisfiesExpression, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray<Node>) => T | undefined): T | undefined {
407            return visitNode(cbNode, node.expression) || visitNode(cbNode, node.type);
408        },
409        [SyntaxKind.MetaProperty]: function forEachChildInMetaProperty<T>(node: MetaProperty, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray<Node>) => T | undefined): T | undefined {
410            return visitNode(cbNode, node.name);
411        },
412        [SyntaxKind.ConditionalExpression]: function forEachChildInConditionalExpression<T>(node: ConditionalExpression, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray<Node>) => T | undefined): T | undefined {
413            return visitNode(cbNode, node.condition) ||
414                visitNode(cbNode, node.questionToken) ||
415                visitNode(cbNode, node.whenTrue) ||
416                visitNode(cbNode, node.colonToken) ||
417                visitNode(cbNode, node.whenFalse);
418        },
419        [SyntaxKind.SpreadElement]: function forEachChildInSpreadElement<T>(node: SpreadElement, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray<Node>) => T | undefined): T | undefined {
420            return visitNode(cbNode, node.expression);
421        },
422        [SyntaxKind.Block]: forEachChildInBlock,
423        [SyntaxKind.ModuleBlock]: forEachChildInBlock,
424        [SyntaxKind.SourceFile]: function forEachChildInSourceFile<T>(node: SourceFile, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray<Node>) => T | undefined): T | undefined {
425            return visitNodes(cbNode, cbNodes, node.statements) ||
426                visitNode(cbNode, node.endOfFileToken);
427        },
428        [SyntaxKind.VariableStatement]: function forEachChildInVariableStatement<T>(node: VariableStatement, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray<Node>) => T | undefined): T | undefined {
429            return visitNodes(cbNode, cbNodes, node.illegalDecorators) ||
430                visitNodes(cbNode, cbNodes, node.modifiers) ||
431                visitNode(cbNode, node.declarationList);
432        },
433        [SyntaxKind.VariableDeclarationList]: function forEachChildInVariableDeclarationList<T>(node: VariableDeclarationList, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray<Node>) => T | undefined): T | undefined {
434            return visitNodes(cbNode, cbNodes, node.declarations);
435        },
436        [SyntaxKind.ExpressionStatement]: function forEachChildInExpressionStatement<T>(node: ExpressionStatement, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray<Node>) => T | undefined): T | undefined {
437            return visitNode(cbNode, node.expression);
438        },
439        [SyntaxKind.IfStatement]: function forEachChildInIfStatement<T>(node: IfStatement, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray<Node>) => T | undefined): T | undefined {
440            return visitNode(cbNode, node.expression) ||
441                visitNode(cbNode, node.thenStatement) ||
442                visitNode(cbNode, node.elseStatement);
443        },
444        [SyntaxKind.DoStatement]: function forEachChildInDoStatement<T>(node: DoStatement, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray<Node>) => T | undefined): T | undefined {
445            return visitNode(cbNode, node.statement) ||
446                visitNode(cbNode, node.expression);
447        },
448        [SyntaxKind.WhileStatement]: function forEachChildInWhileStatement<T>(node: WhileStatement, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray<Node>) => T | undefined): T | undefined {
449            return visitNode(cbNode, node.expression) ||
450                visitNode(cbNode, node.statement);
451        },
452        [SyntaxKind.ForStatement]: function forEachChildInForStatement<T>(node: ForStatement, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray<Node>) => T | undefined): T | undefined {
453            return visitNode(cbNode, node.initializer) ||
454                visitNode(cbNode, node.condition) ||
455                visitNode(cbNode, node.incrementor) ||
456                visitNode(cbNode, node.statement);
457        },
458        [SyntaxKind.ForInStatement]: function forEachChildInForInStatement<T>(node: ForInStatement, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray<Node>) => T | undefined): T | undefined {
459            return visitNode(cbNode, node.initializer) ||
460                visitNode(cbNode, node.expression) ||
461                visitNode(cbNode, node.statement);
462        },
463        [SyntaxKind.ForOfStatement]: function forEachChildInForOfStatement<T>(node: ForOfStatement, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray<Node>) => T | undefined): T | undefined {
464            return visitNode(cbNode, node.awaitModifier) ||
465                visitNode(cbNode, node.initializer) ||
466                visitNode(cbNode, node.expression) ||
467                visitNode(cbNode, node.statement);
468        },
469        [SyntaxKind.ContinueStatement]: forEachChildInContinueOrBreakStatement,
470        [SyntaxKind.BreakStatement]: forEachChildInContinueOrBreakStatement,
471        [SyntaxKind.ReturnStatement]: function forEachChildInReturnStatement<T>(node: ReturnStatement, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray<Node>) => T | undefined): T | undefined {
472            return visitNode(cbNode, node.expression);
473        },
474        [SyntaxKind.WithStatement]: function forEachChildInWithStatement<T>(node: WithStatement, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray<Node>) => T | undefined): T | undefined {
475            return visitNode(cbNode, node.expression) ||
476                visitNode(cbNode, node.statement);
477        },
478        [SyntaxKind.SwitchStatement]: function forEachChildInSwitchStatement<T>(node: SwitchStatement, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray<Node>) => T | undefined): T | undefined {
479            return visitNode(cbNode, node.expression) ||
480                visitNode(cbNode, node.caseBlock);
481        },
482        [SyntaxKind.CaseBlock]: function forEachChildInCaseBlock<T>(node: CaseBlock, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray<Node>) => T | undefined): T | undefined {
483            return visitNodes(cbNode, cbNodes, node.clauses);
484        },
485        [SyntaxKind.CaseClause]: function forEachChildInCaseClause<T>(node: CaseClause, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray<Node>) => T | undefined): T | undefined {
486            return visitNode(cbNode, node.expression) ||
487                visitNodes(cbNode, cbNodes, node.statements);
488        },
489        [SyntaxKind.DefaultClause]: function forEachChildInDefaultClause<T>(node: DefaultClause, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray<Node>) => T | undefined): T | undefined {
490            return visitNodes(cbNode, cbNodes, node.statements);
491        },
492        [SyntaxKind.LabeledStatement]: function forEachChildInLabeledStatement<T>(node: LabeledStatement, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray<Node>) => T | undefined): T | undefined {
493            return visitNode(cbNode, node.label) ||
494                visitNode(cbNode, node.statement);
495        },
496        [SyntaxKind.ThrowStatement]: function forEachChildInThrowStatement<T>(node: ThrowStatement, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray<Node>) => T | undefined): T | undefined {
497            return visitNode(cbNode, node.expression);
498        },
499        [SyntaxKind.TryStatement]: function forEachChildInTryStatement<T>(node: TryStatement, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray<Node>) => T | undefined): T | undefined {
500            return visitNode(cbNode, node.tryBlock) ||
501                visitNode(cbNode, node.catchClause) ||
502                visitNode(cbNode, node.finallyBlock);
503        },
504        [SyntaxKind.CatchClause]: function forEachChildInCatchClause<T>(node: CatchClause, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray<Node>) => T | undefined): T | undefined {
505            return visitNode(cbNode, node.variableDeclaration) ||
506                visitNode(cbNode, node.block);
507        },
508        [SyntaxKind.Decorator]: function forEachChildInDecorator<T>(node: Decorator, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray<Node>) => T | undefined): T | undefined {
509            return visitNode(cbNode, node.expression);
510        },
511        [SyntaxKind.ClassDeclaration]: forEachChildInClassDeclarationOrExpression,
512        [SyntaxKind.ClassExpression]: forEachChildInClassDeclarationOrExpression,
513        [SyntaxKind.StructDeclaration]: forEachChildInClassDeclarationOrExpression,
514        [SyntaxKind.AnnotationDeclaration]: forEachChildInAnnotationDeclaration,
515        [SyntaxKind.InterfaceDeclaration]: function forEachChildInInterfaceDeclaration<T>(node: InterfaceDeclaration, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray<Node>) => T | undefined): T | undefined {
516            return visitNodes(cbNode, cbNodes, node.illegalDecorators) ||
517                visitNodes(cbNode, cbNodes, node.modifiers) ||
518                visitNode(cbNode, node.name) ||
519                visitNodes(cbNode, cbNodes, node.typeParameters) ||
520                visitNodes(cbNode, cbNodes, node.heritageClauses) ||
521                visitNodes(cbNode, cbNodes, node.members);
522        },
523        [SyntaxKind.TypeAliasDeclaration]: function forEachChildInTypeAliasDeclaration<T>(node: TypeAliasDeclaration, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray<Node>) => T | undefined): T | undefined {
524            return visitNodes(cbNode, cbNodes, node.illegalDecorators) ||
525                visitNodes(cbNode, cbNodes, node.modifiers) ||
526                visitNode(cbNode, node.name) ||
527                visitNodes(cbNode, cbNodes, node.typeParameters) ||
528                visitNode(cbNode, node.type);
529        },
530        [SyntaxKind.EnumDeclaration]: function forEachChildInEnumDeclaration<T>(node: EnumDeclaration, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray<Node>) => T | undefined): T | undefined {
531            return visitNodes(cbNode, cbNodes, node.illegalDecorators) ||
532                visitNodes(cbNode, cbNodes, node.modifiers) ||
533                visitNode(cbNode, node.name) ||
534                visitNodes(cbNode, cbNodes, node.members);
535        },
536        [SyntaxKind.EnumMember]: function forEachChildInEnumMember<T>(node: EnumMember, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray<Node>) => T | undefined): T | undefined {
537            return visitNode(cbNode, node.name) ||
538                visitNode(cbNode, node.initializer);
539        },
540        [SyntaxKind.ModuleDeclaration]: function forEachChildInModuleDeclaration<T>(node: ModuleDeclaration, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray<Node>) => T | undefined): T | undefined {
541            return visitNodes(cbNode, cbNodes, node.illegalDecorators) ||
542                visitNodes(cbNode, cbNodes, node.modifiers) ||
543                visitNode(cbNode, node.name) ||
544                visitNode(cbNode, node.body);
545        },
546        [SyntaxKind.ImportEqualsDeclaration]: function forEachChildInImportEqualsDeclaration<T>(node: ImportEqualsDeclaration, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray<Node>) => T | undefined): T | undefined {
547            return visitNodes(cbNode, cbNodes, node.illegalDecorators) ||
548                visitNodes(cbNode, cbNodes, node.modifiers) ||
549                visitNode(cbNode, node.name) ||
550                visitNode(cbNode, node.moduleReference);
551        },
552        [SyntaxKind.ImportDeclaration]: function forEachChildInImportDeclaration<T>(node: ImportDeclaration, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray<Node>) => T | undefined): T | undefined {
553            return visitNodes(cbNode, cbNodes, node.illegalDecorators) ||
554                visitNodes(cbNode, cbNodes, node.modifiers) ||
555                visitNode(cbNode, node.importClause) ||
556                visitNode(cbNode, node.moduleSpecifier) ||
557                visitNode(cbNode, node.assertClause);
558        },
559        [SyntaxKind.ImportClause]: function forEachChildInImportClause<T>(node: ImportClause, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray<Node>) => T | undefined): T | undefined {
560            return visitNode(cbNode, node.name) ||
561                visitNode(cbNode, node.namedBindings);
562        },
563        [SyntaxKind.AssertClause]: function forEachChildInAssertClause<T>(node: AssertClause, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray<Node>) => T | undefined): T | undefined {
564            return visitNodes(cbNode, cbNodes, node.elements);
565        },
566        [SyntaxKind.AssertEntry]: function forEachChildInAssertEntry<T>(node: AssertEntry, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray<Node>) => T | undefined): T | undefined {
567            return visitNode(cbNode, node.name) ||
568                visitNode(cbNode, node.value);
569        },
570        [SyntaxKind.NamespaceExportDeclaration]: function forEachChildInNamespaceExportDeclaration<T>(node: NamespaceExportDeclaration, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray<Node>) => T | undefined): T | undefined {
571            return visitNodes(cbNode, cbNodes, node.illegalDecorators) ||
572                visitNode(cbNode, node.name);
573        },
574        [SyntaxKind.NamespaceImport]: function forEachChildInNamespaceImport<T>(node: NamespaceImport, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray<Node>) => T | undefined): T | undefined {
575            return visitNode(cbNode, node.name);
576        },
577        [SyntaxKind.NamespaceExport]: function forEachChildInNamespaceExport<T>(node: NamespaceExport, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray<Node>) => T | undefined): T | undefined {
578            return visitNode(cbNode, node.name);
579        },
580        [SyntaxKind.NamedImports]: forEachChildInNamedImportsOrExports,
581        [SyntaxKind.NamedExports]: forEachChildInNamedImportsOrExports,
582        [SyntaxKind.ExportDeclaration]: function forEachChildInExportDeclaration<T>(node: ExportDeclaration, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray<Node>) => T | undefined): T | undefined {
583            return visitNodes(cbNode, cbNodes, node.illegalDecorators) ||
584                visitNodes(cbNode, cbNodes, node.modifiers) ||
585                visitNode(cbNode, node.exportClause) ||
586                visitNode(cbNode, node.moduleSpecifier) ||
587                visitNode(cbNode, node.assertClause);
588        },
589        [SyntaxKind.ImportSpecifier]: forEachChildInImportOrExportSpecifier,
590        [SyntaxKind.ExportSpecifier]: forEachChildInImportOrExportSpecifier,
591        [SyntaxKind.ExportAssignment]: function forEachChildInExportAssignment<T>(node: ExportAssignment, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray<Node>) => T | undefined): T | undefined {
592            return visitNodes(cbNode, cbNodes, node.illegalDecorators) ||
593                visitNodes(cbNode, cbNodes, node.modifiers) ||
594                visitNode(cbNode, node.expression);
595        },
596        [SyntaxKind.TemplateExpression]: function forEachChildInTemplateExpression<T>(node: TemplateExpression, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray<Node>) => T | undefined): T | undefined {
597            return visitNode(cbNode, node.head) ||
598                visitNodes(cbNode, cbNodes, node.templateSpans);
599        },
600        [SyntaxKind.TemplateSpan]: function forEachChildInTemplateSpan<T>(node: TemplateSpan, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray<Node>) => T | undefined): T | undefined {
601            return visitNode(cbNode, node.expression) ||
602                visitNode(cbNode, node.literal);
603        },
604        [SyntaxKind.TemplateLiteralType]: function forEachChildInTemplateLiteralType<T>(node: TemplateLiteralTypeNode, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray<Node>) => T | undefined): T | undefined {
605            return visitNode(cbNode, node.head) ||
606                visitNodes(cbNode, cbNodes, node.templateSpans);
607        },
608        [SyntaxKind.TemplateLiteralTypeSpan]: function forEachChildInTemplateLiteralTypeSpan<T>(node: TemplateLiteralTypeSpan, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray<Node>) => T | undefined): T | undefined {
609            return visitNode(cbNode, node.type) ||
610                visitNode(cbNode, node.literal);
611        },
612        [SyntaxKind.ComputedPropertyName]: function forEachChildInComputedPropertyName<T>(node: ComputedPropertyName, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray<Node>) => T | undefined): T | undefined {
613            return visitNode(cbNode, node.expression);
614        },
615        [SyntaxKind.HeritageClause]: function forEachChildInHeritageClause<T>(node: HeritageClause, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray<Node>) => T | undefined): T | undefined {
616            return visitNodes(cbNode, cbNodes, node.types);
617        },
618        [SyntaxKind.ExpressionWithTypeArguments]: function forEachChildInExpressionWithTypeArguments<T>(node: ExpressionWithTypeArguments, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray<Node>) => T | undefined): T | undefined {
619            return visitNode(cbNode, node.expression) ||
620                visitNodes(cbNode, cbNodes, node.typeArguments);
621        },
622        [SyntaxKind.ExternalModuleReference]: function forEachChildInExternalModuleReference<T>(node: ExternalModuleReference, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray<Node>) => T | undefined): T | undefined {
623            return visitNode(cbNode, node.expression);
624        },
625        [SyntaxKind.MissingDeclaration]: function forEachChildInMissingDeclaration<T>(node: MissingDeclaration, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray<Node>) => T | undefined): T | undefined {
626            return visitNodes(cbNode, cbNodes, node.illegalDecorators) ||
627                visitNodes(cbNode, cbNodes, node.modifiers);
628        },
629        [SyntaxKind.CommaListExpression]: function forEachChildInCommaListExpression<T>(node: CommaListExpression, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray<Node>) => T | undefined): T | undefined {
630            return visitNodes(cbNode, cbNodes, node.elements);
631        },
632        [SyntaxKind.JsxElement]: function forEachChildInJsxElement<T>(node: JsxElement, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray<Node>) => T | undefined): T | undefined {
633            return visitNode(cbNode, node.openingElement) ||
634                visitNodes(cbNode, cbNodes, node.children) ||
635                visitNode(cbNode, node.closingElement);
636        },
637        [SyntaxKind.JsxFragment]: function forEachChildInJsxFragment<T>(node: JsxFragment, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray<Node>) => T | undefined): T | undefined {
638            return visitNode(cbNode, node.openingFragment) ||
639                visitNodes(cbNode, cbNodes, node.children) ||
640                visitNode(cbNode, node.closingFragment);
641        },
642        [SyntaxKind.JsxSelfClosingElement]: forEachChildInJsxOpeningOrSelfClosingElement,
643        [SyntaxKind.JsxOpeningElement]: forEachChildInJsxOpeningOrSelfClosingElement,
644        [SyntaxKind.JsxAttributes]: function forEachChildInJsxAttributes<T>(node: JsxAttributes, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray<Node>) => T | undefined): T | undefined {
645            return visitNodes(cbNode, cbNodes, node.properties);
646        },
647        [SyntaxKind.JsxAttribute]: function forEachChildInJsxAttribute<T>(node: JsxAttribute, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray<Node>) => T | undefined): T | undefined {
648            return visitNode(cbNode, node.name) ||
649                visitNode(cbNode, node.initializer);
650        },
651        [SyntaxKind.JsxSpreadAttribute]: function forEachChildInJsxSpreadAttribute<T>(node: JsxSpreadAttribute, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray<Node>) => T | undefined): T | undefined {
652            return visitNode(cbNode, node.expression);
653        },
654        [SyntaxKind.JsxExpression]: function forEachChildInJsxExpression<T>(node: JsxExpression, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray<Node>) => T | undefined): T | undefined {
655            return visitNode(cbNode, node.dotDotDotToken) ||
656                visitNode(cbNode, node.expression);
657        },
658        [SyntaxKind.JsxClosingElement]: function forEachChildInJsxClosingElement<T>(node: JsxClosingElement, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray<Node>) => T | undefined): T | undefined {
659            return visitNode(cbNode, node.tagName);
660        },
661        [SyntaxKind.OptionalType]: forEachChildInOptionalRestOrJSDocParameterModifier,
662        [SyntaxKind.RestType]: forEachChildInOptionalRestOrJSDocParameterModifier,
663        [SyntaxKind.JSDocTypeExpression]: forEachChildInOptionalRestOrJSDocParameterModifier,
664        [SyntaxKind.JSDocNonNullableType]: forEachChildInOptionalRestOrJSDocParameterModifier,
665        [SyntaxKind.JSDocNullableType]: forEachChildInOptionalRestOrJSDocParameterModifier,
666        [SyntaxKind.JSDocOptionalType]: forEachChildInOptionalRestOrJSDocParameterModifier,
667        [SyntaxKind.JSDocVariadicType]: forEachChildInOptionalRestOrJSDocParameterModifier,
668        [SyntaxKind.JSDocFunctionType]: function forEachChildInJSDocFunctionType<T>(node: JSDocFunctionType, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray<Node>) => T | undefined): T | undefined {
669            return visitNodes(cbNode, cbNodes, node.parameters) ||
670                visitNode(cbNode, node.type);
671        },
672        [SyntaxKind.JSDoc]: function forEachChildInJSDoc<T>(node: JSDoc, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray<Node>) => T | undefined): T | undefined {
673            return (typeof node.comment === "string" ? undefined : visitNodes(cbNode, cbNodes, node.comment))
674                || visitNodes(cbNode, cbNodes, node.tags);
675        },
676        [SyntaxKind.JSDocSeeTag]: function forEachChildInJSDocSeeTag<T>(node: JSDocSeeTag, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray<Node>) => T | undefined): T | undefined {
677            return visitNode(cbNode, node.tagName) ||
678                visitNode(cbNode, node.name) ||
679                (typeof node.comment === "string" ? undefined : visitNodes(cbNode, cbNodes, node.comment));
680        },
681        [SyntaxKind.JSDocNameReference]: function forEachChildInJSDocNameReference<T>(node: JSDocNameReference, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray<Node>) => T | undefined): T | undefined {
682            return visitNode(cbNode, node.name);
683        },
684        [SyntaxKind.JSDocMemberName]: function forEachChildInJSDocMemberName<T>(node: JSDocMemberName, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray<Node>) => T | undefined): T | undefined {
685            return visitNode(cbNode, node.left) ||
686                visitNode(cbNode, node.right);
687        },
688        [SyntaxKind.JSDocParameterTag]: forEachChildInJSDocParameterOrPropertyTag,
689        [SyntaxKind.JSDocPropertyTag]: forEachChildInJSDocParameterOrPropertyTag,
690        [SyntaxKind.JSDocAuthorTag]: function forEachChildInJSDocAuthorTag<T>(node: JSDocAuthorTag, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray<Node>) => T | undefined): T | undefined {
691            return visitNode(cbNode, node.tagName) ||
692                (typeof node.comment === "string" ? undefined : visitNodes(cbNode, cbNodes, node.comment));
693        },
694        [SyntaxKind.JSDocImplementsTag]: function forEachChildInJSDocImplementsTag<T>(node: JSDocImplementsTag, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray<Node>) => T | undefined): T | undefined {
695            return visitNode(cbNode, node.tagName) ||
696                visitNode(cbNode, node.class) ||
697                (typeof node.comment === "string" ? undefined : visitNodes(cbNode, cbNodes, node.comment));
698        },
699        [SyntaxKind.JSDocAugmentsTag]: function forEachChildInJSDocAugmentsTag<T>(node: JSDocAugmentsTag, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray<Node>) => T | undefined): T | undefined {
700            return visitNode(cbNode, node.tagName) ||
701                visitNode(cbNode, node.class) ||
702                (typeof node.comment === "string" ? undefined : visitNodes(cbNode, cbNodes, node.comment));
703        },
704        [SyntaxKind.JSDocTemplateTag]: function forEachChildInJSDocTemplateTag<T>(node: JSDocTemplateTag, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray<Node>) => T | undefined): T | undefined {
705            return visitNode(cbNode, node.tagName) ||
706                visitNode(cbNode, node.constraint) ||
707                visitNodes(cbNode, cbNodes, node.typeParameters) ||
708                (typeof node.comment === "string" ? undefined : visitNodes(cbNode, cbNodes, node.comment));
709        },
710        [SyntaxKind.JSDocTypedefTag]: function forEachChildInJSDocTypedefTag<T>(node: JSDocTypedefTag, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray<Node>) => T | undefined): T | undefined {
711            return visitNode(cbNode, node.tagName) ||
712                (node.typeExpression &&
713                    node.typeExpression.kind === SyntaxKind.JSDocTypeExpression
714                    ? visitNode(cbNode, node.typeExpression) ||
715                    visitNode(cbNode, node.fullName) ||
716                    (typeof node.comment === "string" ? undefined : visitNodes(cbNode, cbNodes, node.comment))
717                    : visitNode(cbNode, node.fullName) ||
718                    visitNode(cbNode, node.typeExpression) ||
719                    (typeof node.comment === "string" ? undefined : visitNodes(cbNode, cbNodes, node.comment)));
720        },
721        [SyntaxKind.JSDocCallbackTag]: function forEachChildInJSDocCallbackTag<T>(node: JSDocCallbackTag, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray<Node>) => T | undefined): T | undefined {
722            return visitNode(cbNode, node.tagName) ||
723                visitNode(cbNode, node.fullName) ||
724                visitNode(cbNode, node.typeExpression) ||
725                (typeof node.comment === "string" ? undefined : visitNodes(cbNode, cbNodes, node.comment));
726        },
727        [SyntaxKind.JSDocReturnTag]: forEachChildInJSDocReturnTag,
728        [SyntaxKind.JSDocTypeTag]: forEachChildInJSDocReturnTag,
729        [SyntaxKind.JSDocThisTag]: forEachChildInJSDocReturnTag,
730        [SyntaxKind.JSDocEnumTag]: forEachChildInJSDocReturnTag,
731        [SyntaxKind.JSDocSignature]: function forEachChildInJSDocSignature<T>(node: JSDocSignature, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray<Node>) => T | undefined): T | undefined {
732            return forEach(node.typeParameters, cbNode) ||
733                forEach(node.parameters, cbNode) ||
734                visitNode(cbNode, node.type);
735        },
736        [SyntaxKind.JSDocLink]: forEachChildInJSDocLinkCodeOrPlain,
737        [SyntaxKind.JSDocLinkCode]: forEachChildInJSDocLinkCodeOrPlain,
738        [SyntaxKind.JSDocLinkPlain]: forEachChildInJSDocLinkCodeOrPlain,
739        [SyntaxKind.JSDocTypeLiteral]: function forEachChildInJSDocTypeLiteral<T>(node: JSDocTypeLiteral, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray<Node>) => T | undefined): T | undefined {
740            return forEach(node.jsDocPropertyTags, cbNode);
741        },
742        [SyntaxKind.JSDocTag]: forEachChildInJSDocTag,
743        [SyntaxKind.JSDocClassTag]: forEachChildInJSDocTag,
744        [SyntaxKind.JSDocPublicTag]: forEachChildInJSDocTag,
745        [SyntaxKind.JSDocPrivateTag]: forEachChildInJSDocTag,
746        [SyntaxKind.JSDocProtectedTag]: forEachChildInJSDocTag,
747        [SyntaxKind.JSDocReadonlyTag]: forEachChildInJSDocTag,
748        [SyntaxKind.JSDocDeprecatedTag]: forEachChildInJSDocTag,
749        [SyntaxKind.JSDocOverrideTag]: forEachChildInJSDocTag,
750        [SyntaxKind.PartiallyEmittedExpression]: forEachChildInPartiallyEmittedExpression,
751    };
752
753    // shared
754
755    function forEachChildInCallOrConstructSignature<T>(node: CallSignatureDeclaration | ConstructSignatureDeclaration, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray<Node>) => T | undefined): T | undefined {
756        return visitNodes(cbNode, cbNodes, node.typeParameters) ||
757            visitNodes(cbNode, cbNodes, node.parameters) ||
758            visitNode(cbNode, node.type);
759    }
760
761    function forEachChildInUnionOrIntersectionType<T>(node: UnionTypeNode | IntersectionTypeNode, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray<Node>) => T | undefined): T | undefined {
762        return visitNodes(cbNode, cbNodes, node.types);
763    }
764
765    function forEachChildInParenthesizedTypeOrTypeOperator<T>(node: ParenthesizedTypeNode | TypeOperatorNode, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray<Node>) => T | undefined): T | undefined {
766        return visitNode(cbNode, node.type);
767    }
768
769    function forEachChildInObjectOrArrayBindingPattern<T>(node: BindingPattern, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray<Node>) => T | undefined): T | undefined {
770        return visitNodes(cbNode, cbNodes, node.elements);
771    }
772
773    function forEachChildInCallOrNewExpression<T>(node: CallExpression | NewExpression, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray<Node>) => T | undefined): T | undefined {
774        return visitNode(cbNode, node.expression) ||
775            // TODO: should we separate these branches out?
776            visitNode(cbNode, (node as CallExpression).questionDotToken) ||
777            visitNodes(cbNode, cbNodes, node.typeArguments) ||
778            visitNodes(cbNode, cbNodes, node.arguments);
779    }
780
781    function forEachChildInBlock<T>(node: Block | ModuleBlock, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray<Node>) => T | undefined): T | undefined {
782        return visitNodes(cbNode, cbNodes, node.statements);
783    }
784
785    function forEachChildInContinueOrBreakStatement<T>(node: ContinueStatement | BreakStatement, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray<Node>) => T | undefined): T | undefined {
786        return visitNode(cbNode, node.label);
787    }
788
789    function forEachChildInClassDeclarationOrExpression<T>(node: ClassDeclaration | ClassExpression | StructDeclaration, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray<Node>) => T | undefined): T | undefined {
790        return visitNodes(cbNode, cbNodes, node.modifiers) ||
791            visitNode(cbNode, node.name) ||
792            visitNodes(cbNode, cbNodes, node.typeParameters) ||
793            visitNodes(cbNode, cbNodes, node.heritageClauses) ||
794            visitNodes(cbNode, cbNodes, node.members);
795    }
796
797    function forEachChildInAnnotationDeclaration<T>(node: AnnotationDeclaration, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray<Node>) => T | undefined): T | undefined {
798        return visitNodes(cbNode, cbNodes, node.modifiers) ||
799            visitNode(cbNode, node.name) ||
800            visitNodes(cbNode, cbNodes, node.members);
801    }
802
803    function forEachChildInNamedImportsOrExports<T>(node: NamedImports | NamedExports, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray<Node>) => T | undefined): T | undefined {
804        return visitNodes(cbNode, cbNodes, node.elements);
805    }
806
807    function forEachChildInImportOrExportSpecifier<T>(node: ImportSpecifier | ExportSpecifier, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray<Node>) => T | undefined): T | undefined {
808        return visitNode(cbNode, node.propertyName) ||
809            visitNode(cbNode, node.name);
810    }
811
812    function forEachChildInJsxOpeningOrSelfClosingElement<T>(node: JsxOpeningLikeElement, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray<Node>) => T | undefined): T | undefined {
813        return visitNode(cbNode, node.tagName) ||
814            visitNodes(cbNode, cbNodes, node.typeArguments) ||
815            visitNode(cbNode, node.attributes);
816    }
817
818    function forEachChildInOptionalRestOrJSDocParameterModifier<T>(node: OptionalTypeNode | RestTypeNode | JSDocTypeExpression | JSDocNullableType | JSDocNonNullableType | JSDocOptionalType | JSDocVariadicType, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray<Node>) => T | undefined): T | undefined {
819        return visitNode(cbNode, node.type);
820    }
821
822    function forEachChildInJSDocParameterOrPropertyTag<T>(node: JSDocParameterTag | JSDocPropertyTag, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray<Node>) => T | undefined): T | undefined {
823        return visitNode(cbNode, node.tagName) ||
824            (node.isNameFirst
825                ? visitNode(cbNode, node.name) || visitNode(cbNode, node.typeExpression)
826                : visitNode(cbNode, node.typeExpression) || visitNode(cbNode, node.name)) ||
827            (typeof node.comment === "string" ? undefined : visitNodes(cbNode, cbNodes, node.comment));
828    }
829
830    function forEachChildInJSDocReturnTag<T>(node: JSDocReturnTag | JSDocTypeTag | JSDocThisTag | JSDocEnumTag, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray<Node>) => T | undefined): T | undefined {
831        return visitNode(cbNode, node.tagName) ||
832            visitNode(cbNode, node.typeExpression) ||
833            (typeof node.comment === "string" ? undefined : visitNodes(cbNode, cbNodes, node.comment));
834    }
835
836    function forEachChildInJSDocLinkCodeOrPlain<T>(node: JSDocLink | JSDocLinkCode | JSDocLinkPlain, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray<Node>) => T | undefined): T | undefined {
837        return visitNode(cbNode, node.name);
838    }
839
840    function forEachChildInJSDocTag<T>(node: JSDocUnknownTag | JSDocClassTag | JSDocPublicTag | JSDocPrivateTag | JSDocProtectedTag | JSDocReadonlyTag | JSDocDeprecatedTag | JSDocOverrideTag, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray<Node>) => T | undefined): T | undefined {
841        return visitNode(cbNode, node.tagName)
842            || (typeof node.comment === "string" ? undefined : visitNodes(cbNode, cbNodes, node.comment));
843    }
844
845    function forEachChildInPartiallyEmittedExpression<T>(node: PartiallyEmittedExpression, cbNode: (node: Node) => T | undefined, _cbNodes?: (nodes: NodeArray<Node>) => T | undefined): T | undefined {
846        return visitNode(cbNode, node.expression);
847    }
848
849    /**
850     * Invokes a callback for each child of the given node. The 'cbNode' callback is invoked for all child nodes
851     * stored in properties. If a 'cbNodes' callback is specified, it is invoked for embedded arrays; otherwise,
852     * embedded arrays are flattened and the 'cbNode' callback is invoked for each element. If a callback returns
853     * a truthy value, iteration stops and that value is returned. Otherwise, undefined is returned.
854     *
855     * @param node a given node to visit its children
856     * @param cbNode a callback to be invoked for all child nodes
857     * @param cbNodes a callback to be invoked for embedded array
858     *
859     * @remarks `forEachChild` must visit the children of a node in the order
860     * that they appear in the source code. The language service depends on this property to locate nodes by position.
861     */
862    export function forEachChild<T>(node: Node, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray<Node>) => T | undefined): T | undefined {
863        if (node === undefined || node.kind <= SyntaxKind.LastToken) {
864            return;
865        }
866        const fn = (forEachChildTable as Record<SyntaxKind, ForEachChildFunction<any>>)[node.kind];
867        return fn === undefined ? undefined : fn(node, cbNode, cbNodes);
868    }
869
870    /** @internal */
871    /**
872     * Invokes a callback for each child of the given node. The 'cbNode' callback is invoked for all child nodes
873     * stored in properties. If a 'cbNodes' callback is specified, it is invoked for embedded arrays; additionally,
874     * unlike `forEachChild`, embedded arrays are flattened and the 'cbNode' callback is invoked for each element.
875     *  If a callback returns a truthy value, iteration stops and that value is returned. Otherwise, undefined is returned.
876     *
877     * @param node a given node to visit its children
878     * @param cbNode a callback to be invoked for all child nodes
879     * @param cbNodes a callback to be invoked for embedded array
880     *
881     * @remarks Unlike `forEachChild`, `forEachChildRecursively` handles recursively invoking the traversal on each child node found,
882     * and while doing so, handles traversing the structure without relying on the callstack to encode the tree structure.
883     */
884    export function forEachChildRecursively<T>(rootNode: Node, cbNode: (node: Node, parent: Node) => T | "skip" | undefined, cbNodes?: (nodes: NodeArray<Node>, parent: Node) => T | "skip" | undefined): T | undefined {
885        const queue: (Node | NodeArray<Node>)[] = gatherPossibleChildren(rootNode);
886        const parents: Node[] = []; // tracks parent references for elements in queue
887        while (parents.length < queue.length) {
888            parents.push(rootNode);
889        }
890        while (queue.length !== 0) {
891            const current = queue.pop()!;
892            const parent = parents.pop()!;
893            if (isArray(current)) {
894                if (cbNodes) {
895                    const res = cbNodes(current, parent);
896                    if (res) {
897                        if (res === "skip") continue;
898                        return res;
899                    }
900                }
901                for (let i = current.length - 1; i >= 0; --i) {
902                    queue.push(current[i]);
903                    parents.push(parent);
904                }
905            }
906            else {
907                const res = cbNode(current, parent);
908                if (res) {
909                    if (res === "skip") continue;
910                    return res;
911                }
912                if (current.kind >= SyntaxKind.FirstNode) {
913                    // add children in reverse order to the queue, so popping gives the first child
914                    for (const child of gatherPossibleChildren(current)) {
915                        queue.push(child);
916                        parents.push(current);
917                    }
918                }
919            }
920        }
921    }
922
923    function gatherPossibleChildren(node: Node) {
924        const children: (Node | NodeArray<Node>)[] = [];
925        forEachChild(node, addWorkItem, addWorkItem); // By using a stack above and `unshift` here, we emulate a depth-first preorder traversal
926        return children;
927
928        function addWorkItem(n: Node | NodeArray<Node>) {
929            children.unshift(n);
930        }
931    }
932
933    export interface CreateSourceFileOptions {
934        languageVersion: ScriptTarget;
935        /**
936         * Controls the format the file is detected as - this can be derived from only the path
937         * and files on disk, but needs to be done with a module resolution cache in scope to be performant.
938         * This is usually `undefined` for compilations that do not have `moduleResolution` values of `node16` or `nodenext`.
939         */
940        impliedNodeFormat?: ModuleKind.ESNext | ModuleKind.CommonJS;
941        /**
942         * Controls how module-y-ness is set for the given file. Usually the result of calling
943         * `getSetExternalModuleIndicator` on a valid `CompilerOptions` object. If not present, the default
944         * check specified by `isFileProbablyExternalModule` will be used to set the field.
945         */
946        setExternalModuleIndicator?: (file: SourceFile) => void;
947        /*@internal*/ packageJsonLocations?: readonly string[];
948        /*@internal*/ packageJsonScope?: PackageJsonInfo;
949    }
950
951    function setExternalModuleIndicator(sourceFile: SourceFile) {
952        sourceFile.externalModuleIndicator = isFileProbablyExternalModule(sourceFile);
953    }
954
955    let sourceFileCompilerOptions: CompilerOptions;
956    export function createSourceFile(fileName: string, sourceText: string, languageVersionOrOptions: ScriptTarget | CreateSourceFileOptions, setParentNodes = false, scriptKind?: ScriptKind, options?: CompilerOptions): SourceFile {
957        tracing?.push(tracing.Phase.Parse, "createSourceFile", { path: fileName }, /*separateBeginAndEnd*/ true);
958        const recordInfo = MemoryDotting.recordStage(MemoryDotting.CREATE_SORUCE_FILE_PARSE);
959        performance.mark("beforeParse");
960        let result: SourceFile;
961        sourceFileCompilerOptions = options ?? defaultInitCompilerOptions;
962        perfLogger.logStartParseSourceFile(fileName);
963        const {
964            languageVersion,
965            setExternalModuleIndicator: overrideSetExternalModuleIndicator,
966            impliedNodeFormat: format
967        } = typeof languageVersionOrOptions === "object" ? languageVersionOrOptions : ({ languageVersion: languageVersionOrOptions } as CreateSourceFileOptions);
968        if (languageVersion === ScriptTarget.JSON) {
969            result = Parser.parseSourceFile(fileName, sourceText, languageVersion, /*syntaxCursor*/ undefined, setParentNodes, ScriptKind.JSON, noop);
970        }
971        else {
972            const setIndicator = format === undefined ? overrideSetExternalModuleIndicator : (file: SourceFile) => {
973                file.impliedNodeFormat = format;
974                return (overrideSetExternalModuleIndicator || setExternalModuleIndicator)(file);
975            };
976            result = Parser.parseSourceFile(fileName, sourceText, languageVersion, /*syntaxCursor*/ undefined, setParentNodes, scriptKind, setIndicator);
977        }
978        perfLogger.logStopParseSourceFile();
979
980        performance.mark("afterParse");
981        MemoryDotting.stopRecordStage(recordInfo);
982        performance.measure("Parse", "beforeParse", "afterParse");
983        tracing?.pop();
984        return result;
985    }
986
987    export function parseIsolatedEntityName(text: string, languageVersion: ScriptTarget): EntityName | undefined {
988        return Parser.parseIsolatedEntityName(text, languageVersion);
989    }
990
991    /**
992     * Parse json text into SyntaxTree and return node and parse errors if any
993     * @param fileName
994     * @param sourceText
995     */
996    export function parseJsonText(fileName: string, sourceText: string): JsonSourceFile {
997        return Parser.parseJsonText(fileName, sourceText);
998    }
999
1000    // See also `isExternalOrCommonJsModule` in utilities.ts
1001    export function isExternalModule(file: SourceFile): boolean {
1002        return file.externalModuleIndicator !== undefined;
1003    }
1004
1005    // Produces a new SourceFile for the 'newText' provided. The 'textChangeRange' parameter
1006    // indicates what changed between the 'text' that this SourceFile has and the 'newText'.
1007    // The SourceFile will be created with the compiler attempting to reuse as many nodes from
1008    // this file as possible.
1009    //
1010    // Note: this function mutates nodes from this SourceFile. That means any existing nodes
1011    // from this SourceFile that are being held onto may change as a result (including
1012    // becoming detached from any SourceFile).  It is recommended that this SourceFile not
1013    // be used once 'update' is called on it.
1014    export function updateSourceFile(sourceFile: SourceFile, newText: string, textChangeRange: TextChangeRange, aggressiveChecks = false, option?: CompilerOptions): SourceFile {
1015        sourceFileCompilerOptions = option ?? defaultInitCompilerOptions;
1016        const newSourceFile = IncrementalParser.updateSourceFile(sourceFile, newText, textChangeRange, aggressiveChecks);
1017        // 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.
1018        // We will manually port the flag to the new source file.
1019        (newSourceFile as Mutable<SourceFile>).flags |= (sourceFile.flags & NodeFlags.PermanentlySetIncrementalFlags);
1020        return newSourceFile;
1021    }
1022
1023    /* @internal */
1024    export function parseIsolatedJSDocComment(content: string, start?: number, length?: number) {
1025        const result = Parser.JSDocParser.parseIsolatedJSDocComment(content, start, length);
1026        if (result && result.jsDoc) {
1027            // because the jsDocComment was parsed out of the source file, it might
1028            // not be covered by the fixupParentReferences.
1029            Parser.fixupParentReferences(result.jsDoc);
1030        }
1031
1032        return result;
1033    }
1034
1035    /* @internal */
1036    // Exposed only for testing.
1037    export function parseJSDocTypeExpressionForTests(content: string, start?: number, length?: number) {
1038        return Parser.JSDocParser.parseJSDocTypeExpressionForTests(content, start, length);
1039    }
1040
1041    // Implement the parser as a singleton module.  We do this for perf reasons because creating
1042    // parser instances can actually be expensive enough to impact us on projects with many source
1043    // files.
1044    namespace Parser {
1045        // Share a single scanner across all calls to parse a source file.  This helps speed things
1046        // up by avoiding the cost of creating/compiling scanners over and over again.
1047        const scanner = createScanner(ScriptTarget.Latest, /*skipTrivia*/ true);
1048
1049        const disallowInAndDecoratorContext = NodeFlags.DisallowInContext | NodeFlags.DecoratorContext;
1050
1051        // capture constructors in 'initializeState' to avoid null checks
1052        let NodeConstructor: new (kind: SyntaxKind, pos: number, end: number) => Node;
1053        let TokenConstructor: new (kind: SyntaxKind, pos: number, end: number) => Node;
1054        let IdentifierConstructor: new (kind: SyntaxKind, pos: number, end: number) => Node;
1055        let PrivateIdentifierConstructor: new (kind: SyntaxKind, pos: number, end: number) => Node;
1056        let SourceFileConstructor: new (kind: SyntaxKind, pos: number, end: number) => Node;
1057
1058        function countNode(node: Node) {
1059            nodeCount++;
1060            return node;
1061        }
1062
1063        // Rather than using `createBaseNodeFactory` here, we establish a `BaseNodeFactory` that closes over the
1064        // constructors above, which are reset each time `initializeState` is called.
1065        const baseNodeFactory: BaseNodeFactory = {
1066            createBaseSourceFileNode: kind => countNode(new SourceFileConstructor(kind, /*pos*/ 0, /*end*/ 0)),
1067            createBaseIdentifierNode: kind => countNode(new IdentifierConstructor(kind, /*pos*/ 0, /*end*/ 0)),
1068            createBasePrivateIdentifierNode: kind => countNode(new PrivateIdentifierConstructor(kind, /*pos*/ 0, /*end*/ 0)),
1069            createBaseTokenNode: kind => countNode(new TokenConstructor(kind, /*pos*/ 0, /*end*/ 0)),
1070            createBaseNode: kind => countNode(new NodeConstructor(kind, /*pos*/ 0, /*end*/ 0))
1071        };
1072
1073        const factory = createNodeFactory(NodeFactoryFlags.NoParenthesizerRules | NodeFactoryFlags.NoNodeConverters | NodeFactoryFlags.NoOriginalNode, baseNodeFactory);
1074
1075        let fileName: string;
1076        let sourceFlags: NodeFlags;
1077        let sourceText: string;
1078        let languageVersion: ScriptTarget;
1079        let scriptKind: ScriptKind;
1080        let languageVariant: LanguageVariant;
1081        let parseDiagnostics: DiagnosticWithDetachedLocation[];
1082        let jsDocDiagnostics: DiagnosticWithDetachedLocation[];
1083        let syntaxCursor: IncrementalParser.SyntaxCursor | undefined;
1084
1085        let currentToken: SyntaxKind;
1086        let nodeCount: number;
1087        let identifiers: ESMap<string, string>;
1088        let privateIdentifiers: ESMap<string, string>;
1089        let identifierCount: number;
1090
1091        let parsingContext: ParsingContext;
1092
1093        let notParenthesizedArrow: Set<number> | undefined;
1094
1095        // Flags that dictate what parsing context we're in.  For example:
1096        // Whether or not we are in strict parsing mode.  All that changes in strict parsing mode is
1097        // that some tokens that would be considered identifiers may be considered keywords.
1098        //
1099        // When adding more parser context flags, consider which is the more common case that the
1100        // flag will be in.  This should be the 'false' state for that flag.  The reason for this is
1101        // that we don't store data in our nodes unless the value is in the *non-default* state.  So,
1102        // for example, more often than code 'allows-in' (or doesn't 'disallow-in').  We opt for
1103        // 'disallow-in' set to 'false'.  Otherwise, if we had 'allowsIn' set to 'true', then almost
1104        // all nodes would need extra state on them to store this info.
1105        //
1106        // Note: 'allowIn' and 'allowYield' track 1:1 with the [in] and [yield] concepts in the ES6
1107        // grammar specification.
1108        //
1109        // An important thing about these context concepts.  By default they are effectively inherited
1110        // while parsing through every grammar production.  i.e. if you don't change them, then when
1111        // you parse a sub-production, it will have the same context values as the parent production.
1112        // This is great most of the time.  After all, consider all the 'expression' grammar productions
1113        // and how nearly all of them pass along the 'in' and 'yield' context values:
1114        //
1115        // EqualityExpression[In, Yield] :
1116        //      RelationalExpression[?In, ?Yield]
1117        //      EqualityExpression[?In, ?Yield] == RelationalExpression[?In, ?Yield]
1118        //      EqualityExpression[?In, ?Yield] != RelationalExpression[?In, ?Yield]
1119        //      EqualityExpression[?In, ?Yield] === RelationalExpression[?In, ?Yield]
1120        //      EqualityExpression[?In, ?Yield] !== RelationalExpression[?In, ?Yield]
1121        //
1122        // Where you have to be careful is then understanding what the points are in the grammar
1123        // where the values are *not* passed along.  For example:
1124        //
1125        // SingleNameBinding[Yield,GeneratorParameter]
1126        //      [+GeneratorParameter]BindingIdentifier[Yield] Initializer[In]opt
1127        //      [~GeneratorParameter]BindingIdentifier[?Yield]Initializer[In, ?Yield]opt
1128        //
1129        // Here this is saying that if the GeneratorParameter context flag is set, that we should
1130        // explicitly set the 'yield' context flag to false before calling into the BindingIdentifier
1131        // and we should explicitly unset the 'yield' context flag before calling into the Initializer.
1132        // production.  Conversely, if the GeneratorParameter context flag is not set, then we
1133        // should leave the 'yield' context flag alone.
1134        //
1135        // Getting this all correct is tricky and requires careful reading of the grammar to
1136        // understand when these values should be changed versus when they should be inherited.
1137        //
1138        // Note: it should not be necessary to save/restore these flags during speculative/lookahead
1139        // parsing.  These context flags are naturally stored and restored through normal recursive
1140        // descent parsing and unwinding.
1141        let contextFlags: NodeFlags;
1142
1143        let etsFlags: EtsFlags;
1144
1145        // Indicates whether we are currently parsing top-level statements.
1146        let topLevel = true;
1147
1148        // Whether or not we've had a parse error since creating the last AST node.  If we have
1149        // encountered an error, it will be stored on the next AST node we create.  Parse errors
1150        // can be broken down into three categories:
1151        //
1152        // 1) An error that occurred during scanning.  For example, an unterminated literal, or a
1153        //    character that was completely not understood.
1154        //
1155        // 2) A token was expected, but was not present.  This type of error is commonly produced
1156        //    by the 'parseExpected' function.
1157        //
1158        // 3) A token was present that no parsing function was able to consume.  This type of error
1159        //    only occurs in the 'abortParsingListOrMoveToNextToken' function when the parser
1160        //    decides to skip the token.
1161        //
1162        // In all of these cases, we want to mark the next node as having had an error before it.
1163        // With this mark, we can know in incremental settings if this node can be reused, or if
1164        // we have to reparse it.  If we don't keep this information around, we may just reuse the
1165        // node.  in that event we would then not produce the same errors as we did before, causing
1166        // significant confusion problems.
1167        //
1168        // Note: it is necessary that this value be saved/restored during speculative/lookahead
1169        // parsing.  During lookahead parsing, we will often create a node.  That node will have
1170        // this value attached, and then this value will be set back to 'false'.  If we decide to
1171        // rewind, we must get back to the same value we had prior to the lookahead.
1172        //
1173        // Note: any errors at the end of the file that do not precede a regular node, should get
1174        // attached to the EOF token.
1175        let parseErrorBeforeNextFinishedNode = false;
1176
1177        let extendEtsComponentDeclaration: { name: string, type: string, instance: string } | undefined;
1178
1179        let stylesEtsComponentDeclaration: { name: string, type: string, instance: string } | undefined;
1180
1181        // A map to record file scope '@styles' function name
1182        const fileStylesComponents = new Map<string, SyntaxKind>();
1183
1184        let currentStructName: string | undefined;
1185
1186        let stateStylesRootNode: string | undefined;
1187
1188        // A map to record struct scope '@styles' method name
1189        const structStylesComponents = new Map<string, { structName: string, kind: SyntaxKind }>();
1190
1191        export function parseSourceFile(fileName: string, sourceText: string, languageVersion: ScriptTarget, syntaxCursor: IncrementalParser.SyntaxCursor | undefined, setParentNodes = false, scriptKind?: ScriptKind, setExternalModuleIndicatorOverride?: (file: SourceFile) => void): SourceFile {
1192            scriptKind = ensureScriptKind(fileName, scriptKind);
1193            if (scriptKind === ScriptKind.JSON) {
1194                const result = parseJsonText(fileName, sourceText, languageVersion, syntaxCursor, setParentNodes);
1195                convertToObjectWorker(result, result.statements[0]?.expression, result.parseDiagnostics, /*returnValue*/ false, /*knownRootOptions*/ undefined, /*jsonConversionNotifier*/ undefined);
1196                result.referencedFiles = emptyArray;
1197                result.typeReferenceDirectives = emptyArray;
1198                result.libReferenceDirectives = emptyArray;
1199                result.amdDependencies = emptyArray;
1200                result.hasNoDefaultLib = false;
1201                result.pragmas = emptyMap as ReadonlyPragmaMap;
1202                return result;
1203            }
1204
1205            initializeState(fileName, sourceText, languageVersion, syntaxCursor, scriptKind);
1206
1207            const result = parseSourceFileWorker(languageVersion, setParentNodes, scriptKind, setExternalModuleIndicatorOverride || setExternalModuleIndicator);
1208
1209            clearState();
1210
1211            return result;
1212        }
1213
1214        export function parseIsolatedEntityName(content: string, languageVersion: ScriptTarget): EntityName | undefined {
1215            // Choice of `isDeclarationFile` should be arbitrary
1216            initializeState("", content, languageVersion, /*syntaxCursor*/ undefined, ScriptKind.JS);
1217            // Prime the scanner.
1218            nextToken();
1219            const entityName = parseEntityName(/*allowReservedWords*/ true);
1220            const isInvalid = token() === SyntaxKind.EndOfFileToken && !parseDiagnostics.length;
1221            clearState();
1222            return isInvalid ? entityName : undefined;
1223        }
1224
1225        export function parseJsonText(fileName: string, sourceText: string, languageVersion: ScriptTarget = ScriptTarget.ES2015, syntaxCursor?: IncrementalParser.SyntaxCursor, setParentNodes = false): JsonSourceFile {
1226            initializeState(fileName, sourceText, languageVersion, syntaxCursor, ScriptKind.JSON);
1227            sourceFlags = contextFlags;
1228
1229            // Prime the scanner.
1230            nextToken();
1231            const pos = getNodePos();
1232            let statements, endOfFileToken;
1233            if (token() === SyntaxKind.EndOfFileToken) {
1234                statements = createNodeArray([], pos, pos);
1235                endOfFileToken = parseTokenNode<EndOfFileToken>();
1236            }
1237            else {
1238                // Loop and synthesize an ArrayLiteralExpression if there are more than
1239                // one top-level expressions to ensure all input text is consumed.
1240                let expressions: Expression[] | Expression | undefined;
1241                while (token() !== SyntaxKind.EndOfFileToken) {
1242                    let expression;
1243                    switch (token()) {
1244                        case SyntaxKind.OpenBracketToken:
1245                            expression = parseArrayLiteralExpression();
1246                            break;
1247                        case SyntaxKind.TrueKeyword:
1248                        case SyntaxKind.FalseKeyword:
1249                        case SyntaxKind.NullKeyword:
1250                            expression = parseTokenNode<BooleanLiteral | NullLiteral>();
1251                            break;
1252                        case SyntaxKind.MinusToken:
1253                            if (lookAhead(() => nextToken() === SyntaxKind.NumericLiteral && nextToken() !== SyntaxKind.ColonToken)) {
1254                                expression = parsePrefixUnaryExpression() as JsonMinusNumericLiteral;
1255                            }
1256                            else {
1257                                expression = parseObjectLiteralExpression();
1258                            }
1259                            break;
1260                        case SyntaxKind.NumericLiteral:
1261                        case SyntaxKind.StringLiteral:
1262                            if (lookAhead(() => nextToken() !== SyntaxKind.ColonToken)) {
1263                                expression = parseLiteralNode() as StringLiteral | NumericLiteral;
1264                                break;
1265                            }
1266                            // falls through
1267                        default:
1268                            expression = parseObjectLiteralExpression();
1269                            break;
1270                    }
1271
1272                    // Error recovery: collect multiple top-level expressions
1273                    if (expressions && isArray(expressions)) {
1274                        expressions.push(expression);
1275                    }
1276                    else if (expressions) {
1277                        expressions = [expressions, expression];
1278                    }
1279                    else {
1280                        expressions = expression;
1281                        if (token() !== SyntaxKind.EndOfFileToken) {
1282                            parseErrorAtCurrentToken(Diagnostics.Unexpected_token);
1283                        }
1284                    }
1285                }
1286
1287                const expression = isArray(expressions) ? finishNode(factory.createArrayLiteralExpression(expressions), pos) : Debug.checkDefined(expressions);
1288                const statement = factory.createExpressionStatement(expression) as JsonObjectExpressionStatement;
1289                finishNode(statement, pos);
1290                statements = createNodeArray([statement], pos);
1291                endOfFileToken = parseExpectedToken(SyntaxKind.EndOfFileToken, Diagnostics.Unexpected_token);
1292            }
1293
1294            // Set source file so that errors will be reported with this file name
1295            const sourceFile = createSourceFile(fileName, ScriptTarget.ES2015, ScriptKind.JSON, /*isDeclaration*/ false, statements, endOfFileToken, sourceFlags, noop);
1296
1297            if (setParentNodes) {
1298                fixupParentReferences(sourceFile);
1299            }
1300
1301            sourceFile.nodeCount = nodeCount;
1302            sourceFile.identifierCount = identifierCount;
1303            sourceFile.identifiers = identifiers;
1304            sourceFile.parseDiagnostics = attachFileToDiagnostics(parseDiagnostics, sourceFile);
1305            if (jsDocDiagnostics) {
1306                sourceFile.jsDocDiagnostics = attachFileToDiagnostics(jsDocDiagnostics, sourceFile);
1307            }
1308
1309            const result = sourceFile as JsonSourceFile;
1310            clearState();
1311            return result;
1312        }
1313
1314        function initializeState(_fileName: string, _sourceText: string, _languageVersion: ScriptTarget, _syntaxCursor: IncrementalParser.SyntaxCursor | undefined, _scriptKind: ScriptKind) {
1315            NodeConstructor = objectAllocator.getNodeConstructor();
1316            TokenConstructor = objectAllocator.getTokenConstructor();
1317            IdentifierConstructor = objectAllocator.getIdentifierConstructor();
1318            PrivateIdentifierConstructor = objectAllocator.getPrivateIdentifierConstructor();
1319            SourceFileConstructor = objectAllocator.getSourceFileConstructor();
1320
1321            fileName = normalizePath(_fileName);
1322            sourceText = _sourceText;
1323            languageVersion = _languageVersion;
1324            syntaxCursor = _syntaxCursor;
1325            scriptKind = _scriptKind;
1326            languageVariant = getLanguageVariant(_scriptKind);
1327
1328            parseDiagnostics = [];
1329            parsingContext = 0;
1330            identifiers = new Map<string, string>();
1331            privateIdentifiers = new Map<string, string>();
1332            identifierCount = 0;
1333            nodeCount = 0;
1334            sourceFlags = 0;
1335            topLevel = true;
1336
1337            switch (scriptKind) {
1338                case ScriptKind.JS:
1339                case ScriptKind.JSX:
1340                    contextFlags = NodeFlags.JavaScriptFile;
1341                    break;
1342                case ScriptKind.JSON:
1343                    contextFlags = NodeFlags.JavaScriptFile | NodeFlags.JsonFile;
1344                    break;
1345                case ScriptKind.ETS:
1346                    contextFlags = NodeFlags.EtsContext;
1347                    break;
1348                default:
1349                    contextFlags = NodeFlags.None;
1350                    break;
1351            }
1352            if (fileName.endsWith(Extension.Ets)) {
1353                contextFlags = NodeFlags.EtsContext;
1354            }
1355            parseErrorBeforeNextFinishedNode = false;
1356
1357            // Initialize and prime the scanner before parsing the source elements.
1358            scanner.setText(sourceText);
1359            scanner.setOnError(scanError);
1360            scanner.setScriptTarget(languageVersion);
1361            scanner.setLanguageVariant(languageVariant);
1362            scanner.setEtsContext(inEtsContext());
1363        }
1364
1365        function clearState() {
1366            // Clear out the text the scanner is pointing at, so it doesn't keep anything alive unnecessarily.
1367            scanner.clearCommentDirectives();
1368            scanner.setText("");
1369            scanner.setOnError(undefined);
1370            scanner.setEtsContext(false);
1371            // Clear any data.  We don't want to accidentally hold onto it for too long.
1372            sourceText = undefined!;
1373            languageVersion = undefined!;
1374            syntaxCursor = undefined;
1375            scriptKind = undefined!;
1376            languageVariant = undefined!;
1377            sourceFlags = 0;
1378            parseDiagnostics = undefined!;
1379            jsDocDiagnostics = undefined!;
1380            parsingContext = 0;
1381            identifiers = undefined!;
1382            notParenthesizedArrow = undefined;
1383            topLevel = true;
1384            extendEtsComponentDeclaration = undefined;
1385            stylesEtsComponentDeclaration = undefined;
1386            stateStylesRootNode = undefined;
1387            fileStylesComponents.clear();
1388            structStylesComponents.clear();
1389        }
1390
1391        function parseSourceFileWorker(languageVersion: ScriptTarget, setParentNodes: boolean, scriptKind: ScriptKind, setExternalModuleIndicator: (file: SourceFile) => void): SourceFile {
1392            const isDeclarationFile = isDeclarationFileName(fileName);
1393            if (isDeclarationFile) {
1394                contextFlags |= NodeFlags.Ambient;
1395            }
1396
1397            sourceFlags = contextFlags;
1398
1399            // Prime the scanner.
1400            nextToken();
1401
1402            let statements = parseList(ParsingContext.SourceElements, parseStatement);
1403            const markedkitImportRanges = new Array<TextRange>();
1404            const sdkPath = getSdkPath(sourceFileCompilerOptions);
1405            statements = (!!sourceFileCompilerOptions.noTransformedKitInParser || !sdkPath || parseDiagnostics.length) ?
1406                statements :
1407                createNodeArray(processKit(factory, statements, sdkPath, markedkitImportRanges, inEtsContext()), statements.pos);
1408            Debug.assert(token() === SyntaxKind.EndOfFileToken);
1409            const endOfFileToken = addJSDocComment(parseTokenNode<EndOfFileToken>());
1410
1411            const sourceFile = createSourceFile(fileName, languageVersion, scriptKind, isDeclarationFile, statements, endOfFileToken, sourceFlags, setExternalModuleIndicator);
1412            if (markedkitImportRanges.length > 0) {
1413                sourceFile.markedKitImportRange = markedkitImportRanges;
1414            }
1415
1416            // A member of ReadonlyArray<T> 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
1417            processCommentPragmas(sourceFile as {} as PragmaContext, sourceText);
1418            processPragmasIntoFields(sourceFile as {} as PragmaContext, reportPragmaDiagnostic);
1419
1420            sourceFile.commentDirectives = scanner.getCommentDirectives();
1421            sourceFile.nodeCount = nodeCount;
1422            sourceFile.identifierCount = identifierCount;
1423            sourceFile.identifiers = identifiers;
1424            sourceFile.parseDiagnostics = attachFileToDiagnostics(parseDiagnostics, sourceFile);
1425            if (jsDocDiagnostics) {
1426                sourceFile.jsDocDiagnostics = attachFileToDiagnostics(jsDocDiagnostics, sourceFile);
1427            }
1428
1429            if (setParentNodes) {
1430                fixupParentReferences(sourceFile);
1431            }
1432
1433            return sourceFile;
1434
1435            function reportPragmaDiagnostic(pos: number, end: number, diagnostic: DiagnosticMessage) {
1436                parseDiagnostics.push(createDetachedDiagnostic(fileName, pos, end, diagnostic));
1437            }
1438        }
1439
1440        function withJSDoc<T extends HasJSDoc>(node: T, hasJSDoc: boolean): T {
1441            return hasJSDoc ? addJSDocComment(node) : node;
1442        }
1443
1444        let hasDeprecatedTag = false;
1445        function addJSDocComment<T extends HasJSDoc>(node: T): T {
1446            Debug.assert(!node.jsDoc); // Should only be called once per node
1447            const jsDoc = mapDefined(getJSDocCommentRanges(node, sourceText), comment => JSDocParser.parseJSDocComment(node, comment.pos, comment.end - comment.pos));
1448            if (jsDoc.length) node.jsDoc = jsDoc;
1449            if (hasDeprecatedTag) {
1450                hasDeprecatedTag = false;
1451                (node as Mutable<T>).flags |= NodeFlags.Deprecated;
1452            }
1453            return node;
1454        }
1455
1456        function reparseTopLevelAwait(sourceFile: SourceFile) {
1457            const savedSyntaxCursor = syntaxCursor;
1458            const baseSyntaxCursor = IncrementalParser.createSyntaxCursor(sourceFile);
1459            syntaxCursor = { currentNode };
1460
1461            const statements: Statement[] = [];
1462            const savedParseDiagnostics = parseDiagnostics;
1463
1464            parseDiagnostics = [];
1465
1466            let pos = 0;
1467            let start = findNextStatementWithAwait(sourceFile.statements, 0);
1468            while (start !== -1) {
1469                // append all statements between pos and start
1470                const prevStatement = sourceFile.statements[pos];
1471                const nextStatement = sourceFile.statements[start];
1472                addRange(statements, sourceFile.statements, pos, start);
1473                pos = findNextStatementWithoutAwait(sourceFile.statements, start);
1474
1475                // append all diagnostics associated with the copied range
1476                const diagnosticStart = findIndex(savedParseDiagnostics, diagnostic => diagnostic.start >= prevStatement.pos);
1477                const diagnosticEnd = diagnosticStart >= 0 ? findIndex(savedParseDiagnostics, diagnostic => diagnostic.start >= nextStatement.pos, diagnosticStart) : -1;
1478                if (diagnosticStart >= 0) {
1479                    addRange(parseDiagnostics, savedParseDiagnostics, diagnosticStart, diagnosticEnd >= 0 ? diagnosticEnd : undefined);
1480                }
1481
1482                // reparse all statements between start and pos. We skip existing diagnostics for the same range and allow the parser to generate new ones.
1483                speculationHelper(() => {
1484                    const savedContextFlags = contextFlags;
1485                    contextFlags |= NodeFlags.AwaitContext;
1486                    scanner.setTextPos(nextStatement.pos);
1487                    nextToken();
1488
1489                    while (token() !== SyntaxKind.EndOfFileToken) {
1490                        const startPos = scanner.getStartPos();
1491                        const statement = parseListElement(ParsingContext.SourceElements, parseStatement);
1492                        statements.push(statement);
1493                        if (startPos === scanner.getStartPos()) {
1494                            nextToken();
1495                        }
1496
1497                        if (pos >= 0) {
1498                            const nonAwaitStatement = sourceFile.statements[pos];
1499                            if (statement.end === nonAwaitStatement.pos) {
1500                                // done reparsing this section
1501                                break;
1502                            }
1503                            if (statement.end > nonAwaitStatement.pos) {
1504                                // we ate into the next statement, so we must reparse it.
1505                                pos = findNextStatementWithoutAwait(sourceFile.statements, pos + 1);
1506                            }
1507                        }
1508                    }
1509
1510                    contextFlags = savedContextFlags;
1511                }, SpeculationKind.Reparse);
1512
1513                // find the next statement containing an `await`
1514                start = pos >= 0 ? findNextStatementWithAwait(sourceFile.statements, pos) : -1;
1515            }
1516
1517            // append all statements between pos and the end of the list
1518            if (pos >= 0) {
1519                const prevStatement = sourceFile.statements[pos];
1520                addRange(statements, sourceFile.statements, pos);
1521
1522                // append all diagnostics associated with the copied range
1523                const diagnosticStart = findIndex(savedParseDiagnostics, diagnostic => diagnostic.start >= prevStatement.pos);
1524                if (diagnosticStart >= 0) {
1525                    addRange(parseDiagnostics, savedParseDiagnostics, diagnosticStart);
1526                }
1527            }
1528
1529            syntaxCursor = savedSyntaxCursor;
1530            return factory.updateSourceFile(sourceFile, setTextRange(factory.createNodeArray(statements), sourceFile.statements));
1531
1532            function containsPossibleTopLevelAwait(node: Node) {
1533                return !(node.flags & NodeFlags.AwaitContext)
1534                    && !!(node.transformFlags & TransformFlags.ContainsPossibleTopLevelAwait);
1535            }
1536
1537            function findNextStatementWithAwait(statements: NodeArray<Statement>, start: number) {
1538                for (let i = start; i < statements.length; i++) {
1539                    if (containsPossibleTopLevelAwait(statements[i])) {
1540                        return i;
1541                    }
1542                }
1543                return -1;
1544            }
1545
1546            function findNextStatementWithoutAwait(statements: NodeArray<Statement>, start: number) {
1547                for (let i = start; i < statements.length; i++) {
1548                    if (!containsPossibleTopLevelAwait(statements[i])) {
1549                        return i;
1550                    }
1551                }
1552                return -1;
1553            }
1554
1555            function currentNode(position: number) {
1556                const node = baseSyntaxCursor.currentNode(position);
1557                if (topLevel && node && containsPossibleTopLevelAwait(node)) {
1558                    node.intersectsChange = true;
1559                }
1560                return node;
1561            }
1562
1563        }
1564
1565        export function fixupParentReferences(rootNode: Node) {
1566            // normally parent references are set during binding. However, for clients that only need
1567            // a syntax tree, and no semantic features, then the binding process is an unnecessary
1568            // overhead.  This functions allows us to set all the parents, without all the expense of
1569            // binding.
1570            setParentRecursive(rootNode, /*incremental*/ true);
1571        }
1572
1573        function createSourceFile(
1574            fileName: string,
1575            languageVersion: ScriptTarget,
1576            scriptKind: ScriptKind,
1577            isDeclarationFile: boolean,
1578            statements: readonly Statement[],
1579            endOfFileToken: EndOfFileToken,
1580            flags: NodeFlags,
1581            setExternalModuleIndicator: (sourceFile: SourceFile) => void): SourceFile {
1582            // code from createNode is inlined here so createNode won't have to deal with special case of creating source files
1583            // this is quite rare comparing to other nodes and createNode should be as fast as possible
1584            let sourceFile = factory.createSourceFile(statements, endOfFileToken, flags);
1585            setTextRangePosWidth(sourceFile, 0, sourceText.length);
1586            setFields(sourceFile);
1587
1588            // If we parsed this as an external module, it may contain top-level await
1589            if (!isDeclarationFile && isExternalModule(sourceFile) && sourceFile.transformFlags & TransformFlags.ContainsPossibleTopLevelAwait) {
1590                sourceFile = reparseTopLevelAwait(sourceFile);
1591                setFields(sourceFile);
1592            }
1593
1594            return sourceFile;
1595
1596            function setFields(sourceFile: SourceFile) {
1597                sourceFile.text = sourceText;
1598                sourceFile.bindDiagnostics = [];
1599                sourceFile.bindSuggestionDiagnostics = undefined;
1600                sourceFile.languageVersion = languageVersion;
1601                sourceFile.fileName = fileName;
1602                sourceFile.languageVariant = getLanguageVariant(scriptKind);
1603                sourceFile.isDeclarationFile = isDeclarationFile;
1604                sourceFile.scriptKind = scriptKind;
1605
1606                setExternalModuleIndicator(sourceFile);
1607                sourceFile.setExternalModuleIndicator = setExternalModuleIndicator;
1608            }
1609        }
1610
1611        function setContextFlag(val: boolean, flag: NodeFlags) {
1612            if (val) {
1613                contextFlags |= flag;
1614            }
1615            else {
1616                contextFlags &= ~flag;
1617            }
1618        }
1619
1620        function setEtsFlag(val: boolean, flag: EtsFlags) {
1621            if (val) {
1622                etsFlags |= flag;
1623            }
1624            else {
1625                etsFlags &= ~flag;
1626            }
1627        }
1628
1629        function setDisallowInContext(val: boolean) {
1630            setContextFlag(val, NodeFlags.DisallowInContext);
1631        }
1632
1633        function setYieldContext(val: boolean) {
1634            setContextFlag(val, NodeFlags.YieldContext);
1635        }
1636
1637        function setDecoratorContext(val: boolean) {
1638            setContextFlag(val, NodeFlags.DecoratorContext);
1639        }
1640
1641        function setAwaitContext(val: boolean) {
1642            setContextFlag(val, NodeFlags.AwaitContext);
1643        }
1644
1645        function setStructContext(val: boolean) {
1646            setEtsFlag(val, EtsFlags.StructContext);
1647        }
1648
1649        function setEtsComponentsContext(val: boolean) {
1650            setEtsFlag(val, EtsFlags.EtsComponentsContext);
1651        }
1652
1653        function setEtsNewExpressionContext(val: boolean) {
1654            setEtsFlag(val, EtsFlags.EtsNewExpressionContext);
1655        }
1656
1657        function setEtsExtendComponentsContext(val: boolean) {
1658            setEtsFlag(val, EtsFlags.EtsExtendComponentsContext);
1659        }
1660
1661        function setEtsStylesComponentsContext(val: boolean) {
1662            setEtsFlag(val, EtsFlags.EtsStylesComponentsContext);
1663        }
1664
1665        function setEtsBuildContext(val: boolean) {
1666            setEtsFlag(val, EtsFlags.EtsBuildContext);
1667        }
1668
1669        function setEtsBuilderContext(val: boolean) {
1670            setEtsFlag(val, EtsFlags.EtsBuilderContext);
1671        }
1672
1673        function setEtsStateStylesContext(val: boolean) {
1674            setEtsFlag(val, EtsFlags.EtsStateStylesContext);
1675        }
1676
1677        function setUICallbackContext(val: boolean) {
1678            setEtsFlag(val, EtsFlags.UICallbackContext);
1679        }
1680
1681        function setSyntaxComponentContext(val: boolean) {
1682            setEtsFlag(val, EtsFlags.SyntaxComponentContext);
1683        }
1684
1685        function doOutsideOfContext<T>(context: NodeFlags, func: () => T): T {
1686            // contextFlagsToClear will contain only the context flags that are
1687            // currently set that we need to temporarily clear
1688            // We don't just blindly reset to the previous flags to ensure
1689            // that we do not mutate cached flags for the incremental
1690            // parser (ThisNodeHasError, ThisNodeOrAnySubNodesHasError, and
1691            // HasAggregatedChildData).
1692            const contextFlagsToClear = context & contextFlags;
1693            if (contextFlagsToClear) {
1694                // clear the requested context flags
1695                setContextFlag(/*val*/ false, contextFlagsToClear);
1696                const result = func();
1697                // restore the context flags we just cleared
1698                setContextFlag(/*val*/ true, contextFlagsToClear);
1699                return result;
1700            }
1701
1702            // no need to do anything special as we are not in any of the requested contexts
1703            return func();
1704        }
1705
1706        function doInsideOfContext<T>(context: NodeFlags, func: () => T): T {
1707            // contextFlagsToSet will contain only the context flags that
1708            // are not currently set that we need to temporarily enable.
1709            // We don't just blindly reset to the previous flags to ensure
1710            // that we do not mutate cached flags for the incremental
1711            // parser (ThisNodeHasError, ThisNodeOrAnySubNodesHasError, and
1712            // HasAggregatedChildData).
1713            const contextFlagsToSet = context & ~contextFlags;
1714            if (contextFlagsToSet) {
1715                // set the requested context flags
1716                setContextFlag(/*val*/ true, contextFlagsToSet);
1717                const result = func();
1718                // reset the context flags we just set
1719                setContextFlag(/*val*/ false, contextFlagsToSet);
1720                return result;
1721            }
1722
1723            // no need to do anything special as we are already in all of the requested contexts
1724            return func();
1725        }
1726
1727        function allowInAnd<T>(func: () => T): T {
1728            return doOutsideOfContext(NodeFlags.DisallowInContext, func);
1729        }
1730
1731        function disallowInAnd<T>(func: () => T): T {
1732            return doInsideOfContext(NodeFlags.DisallowInContext, func);
1733        }
1734
1735        function allowConditionalTypesAnd<T>(func: () => T): T {
1736            return doOutsideOfContext(NodeFlags.DisallowConditionalTypesContext, func);
1737        }
1738
1739        function disallowConditionalTypesAnd<T>(func: () => T): T {
1740            return doInsideOfContext(NodeFlags.DisallowConditionalTypesContext, func);
1741        }
1742
1743        function doInYieldContext<T>(func: () => T): T {
1744            return doInsideOfContext(NodeFlags.YieldContext, func);
1745        }
1746
1747        function doInDecoratorContext<T>(func: () => T): T {
1748            // setting Ets Extend Components
1749            const extendDecorator = sourceFileCompilerOptions.ets?.extend?.decorator ?? "Extend";
1750            if (token() === SyntaxKind.Identifier && scanner.getTokenText() === extendDecorator) {
1751                setEtsFlag(true, EtsFlags.EtsExtendComponentsContext);
1752            }
1753            // setting Ets Styles Components
1754            const stylesDecorator = sourceFileCompilerOptions.ets?.styles?.decorator ?? "Styles";
1755            if (token() === SyntaxKind.Identifier && scanner.getTokenText() === stylesDecorator) {
1756                setEtsFlag(true, EtsFlags.EtsStylesComponentsContext);
1757            }
1758            return doInsideOfContext(NodeFlags.DecoratorContext, func);
1759        }
1760
1761        function doInAwaitContext<T>(func: () => T): T {
1762            return doInsideOfContext(NodeFlags.AwaitContext, func);
1763        }
1764
1765        function doOutsideOfAwaitContext<T>(func: () => T): T {
1766            return doOutsideOfContext(NodeFlags.AwaitContext, func);
1767        }
1768
1769        function doInYieldAndAwaitContext<T>(func: () => T): T {
1770            return doInsideOfContext(NodeFlags.YieldContext | NodeFlags.AwaitContext, func);
1771        }
1772
1773        function doOutsideOfYieldAndAwaitContext<T>(func: () => T): T {
1774            return doOutsideOfContext(NodeFlags.YieldContext | NodeFlags.AwaitContext, func);
1775        }
1776
1777        function inContext(flags: NodeFlags) {
1778            return (contextFlags & flags) !== 0;
1779        }
1780
1781        function inEtsFlagsContext(flags: EtsFlags) {
1782            return (etsFlags & flags) !== 0;
1783        }
1784
1785        function inYieldContext() {
1786            return inContext(NodeFlags.YieldContext);
1787        }
1788
1789        function inDisallowInContext() {
1790            return inContext(NodeFlags.DisallowInContext);
1791        }
1792
1793        function inDisallowConditionalTypesContext() {
1794            return inContext(NodeFlags.DisallowConditionalTypesContext);
1795        }
1796
1797        function inDecoratorContext() {
1798            return inContext(NodeFlags.DecoratorContext);
1799        }
1800
1801        function inAwaitContext() {
1802            return inContext(NodeFlags.AwaitContext);
1803        }
1804
1805        function parseErrorAtCurrentToken(message: DiagnosticMessage, arg0?: any): DiagnosticWithDetachedLocation | undefined {
1806            return parseErrorAt(scanner.getTokenPos(), scanner.getTextPos(), message, arg0);
1807        }
1808
1809        function inEtsContext() {
1810            return inContext(NodeFlags.EtsContext);
1811        }
1812
1813        function inStructContext() {
1814            return inEtsContext() && inEtsFlagsContext(EtsFlags.StructContext);
1815        }
1816
1817        function inEtsComponentsContext() {
1818            return inEtsContext() && inEtsFlagsContext(EtsFlags.EtsComponentsContext);
1819        }
1820
1821        function inEtsNewExpressionContext() {
1822            return inEtsContext() && inEtsFlagsContext(EtsFlags.EtsNewExpressionContext);
1823        }
1824
1825        function inEtsExtendComponentsContext() {
1826            return inEtsContext() && inEtsFlagsContext(EtsFlags.EtsExtendComponentsContext);
1827        }
1828
1829        function inEtsStylesComponentsContext() {
1830            return inEtsContext() && inEtsFlagsContext(EtsFlags.EtsStylesComponentsContext);
1831        }
1832
1833        function inBuildContext() {
1834            return inEtsContext() && inStructContext() && inEtsFlagsContext(EtsFlags.EtsBuildContext);
1835        }
1836
1837        function inBuilderContext() {
1838            return inEtsContext() && inEtsFlagsContext(EtsFlags.EtsBuilderContext);
1839        }
1840
1841        function inEtsStateStylesContext() {
1842            return inEtsContext() && (inBuildContext() || inBuilderContext() || inEtsExtendComponentsContext() || inEtsStylesComponentsContext()) && inEtsFlagsContext(EtsFlags.EtsStateStylesContext);
1843        }
1844
1845        function inUICallbackContext() {
1846            return inEtsContext() && (inBuildContext() || inBuilderContext()) && inEtsFlagsContext(EtsFlags.UICallbackContext);
1847        }
1848
1849        function inSyntaxComponentContext() {
1850            return inEtsContext() && (inBuildContext() || inBuilderContext()) && inEtsFlagsContext(EtsFlags.SyntaxComponentContext);
1851        }
1852
1853        function inEtsAnnotationContext() {
1854            return inEtsContext() && sourceFileCompilerOptions?.etsAnnotationsEnable === true;
1855        }
1856
1857        function parseErrorAtPosition(start: number, length: number, message: DiagnosticMessage, arg0?: any): DiagnosticWithDetachedLocation | undefined {
1858            // Don't report another error if it would just be at the same position as the last error.
1859            const lastError = lastOrUndefined(parseDiagnostics);
1860            let result: DiagnosticWithDetachedLocation | undefined;
1861            if (!lastError || start !== lastError.start) {
1862                result = createDetachedDiagnostic(fileName, start, length, message, arg0);
1863                parseDiagnostics.push(result);
1864            }
1865
1866            // Mark that we've encountered an error.  We'll set an appropriate bit on the next
1867            // node we finish so that it can't be reused incrementally.
1868            parseErrorBeforeNextFinishedNode = true;
1869            return result;
1870        }
1871
1872        function parseErrorAt(start: number, end: number, message: DiagnosticMessage, arg0?: any): DiagnosticWithDetachedLocation | undefined {
1873            return parseErrorAtPosition(start, end - start, message, arg0);
1874        }
1875
1876        function parseErrorAtRange(range: TextRange, message: DiagnosticMessage, arg0?: any): void {
1877            parseErrorAt(range.pos, range.end, message, arg0);
1878        }
1879
1880        function scanError(message: DiagnosticMessage, length: number): void {
1881            parseErrorAtPosition(scanner.getTextPos(), length, message);
1882        }
1883
1884        function getNodePos(): number {
1885            return scanner.getStartPos();
1886        }
1887
1888        function hasPrecedingJSDocComment() {
1889            return scanner.hasPrecedingJSDocComment();
1890        }
1891
1892        // Use this function to access the current token instead of reading the currentToken
1893        // variable. Since function results aren't narrowed in control flow analysis, this ensures
1894        // that the type checker doesn't make wrong assumptions about the type of the current
1895        // token (e.g. a call to nextToken() changes the current token but the checker doesn't
1896        // reason about this side effect).  Mainstream VMs inline simple functions like this, so
1897        // there is no performance penalty.
1898        function token(): SyntaxKind {
1899            return currentToken;
1900        }
1901
1902        function nextTokenWithoutCheck() {
1903            return currentToken = scanner.scan();
1904        }
1905
1906        function nextTokenAnd<T>(func: () => T): T {
1907            nextToken();
1908            return func();
1909        }
1910
1911        function nextToken(): SyntaxKind {
1912            // if the keyword had an escape
1913            if (isKeyword(currentToken) && (scanner.hasUnicodeEscape() || scanner.hasExtendedUnicodeEscape())) {
1914                // issue a parse error for the escape
1915                parseErrorAt(scanner.getTokenPos(), scanner.getTextPos(), Diagnostics.Keywords_cannot_contain_escape_characters);
1916            }
1917            return nextTokenWithoutCheck();
1918        }
1919
1920        function nextTokenJSDoc(): JSDocSyntaxKind {
1921            return currentToken = scanner.scanJsDocToken();
1922        }
1923
1924        function reScanGreaterToken(): SyntaxKind {
1925            return currentToken = scanner.reScanGreaterToken();
1926        }
1927
1928        function reScanSlashToken(): SyntaxKind {
1929            return currentToken = scanner.reScanSlashToken();
1930        }
1931
1932        function reScanTemplateToken(isTaggedTemplate: boolean): SyntaxKind {
1933            return currentToken = scanner.reScanTemplateToken(isTaggedTemplate);
1934        }
1935
1936        function reScanTemplateHeadOrNoSubstitutionTemplate(): SyntaxKind {
1937            return currentToken = scanner.reScanTemplateHeadOrNoSubstitutionTemplate();
1938        }
1939
1940        function reScanLessThanToken(): SyntaxKind {
1941            return currentToken = scanner.reScanLessThanToken();
1942        }
1943
1944        function reScanHashToken(): SyntaxKind {
1945            return currentToken = scanner.reScanHashToken();
1946        }
1947
1948        function scanJsxIdentifier(): SyntaxKind {
1949            return currentToken = scanner.scanJsxIdentifier();
1950        }
1951
1952        function scanJsxText(): SyntaxKind {
1953            return currentToken = scanner.scanJsxToken();
1954        }
1955
1956        function scanJsxAttributeValue(): SyntaxKind {
1957            return currentToken = scanner.scanJsxAttributeValue();
1958        }
1959
1960        function speculationHelper<T>(callback: () => T, speculationKind: SpeculationKind): T {
1961            // Keep track of the state we'll need to rollback to if lookahead fails (or if the
1962            // caller asked us to always reset our state).
1963            const saveToken = currentToken;
1964            const saveParseDiagnosticsLength = parseDiagnostics.length;
1965            const saveParseErrorBeforeNextFinishedNode = parseErrorBeforeNextFinishedNode;
1966
1967            // Note: it is not actually necessary to save/restore the context flags here.  That's
1968            // because the saving/restoring of these flags happens naturally through the recursive
1969            // descent nature of our parser.  However, we still store this here just so we can
1970            // assert that invariant holds.
1971            const saveContextFlags = contextFlags;
1972
1973            // If we're only looking ahead, then tell the scanner to only lookahead as well.
1974            // Otherwise, if we're actually speculatively parsing, then tell the scanner to do the
1975            // same.
1976            const result = speculationKind !== SpeculationKind.TryParse
1977                ? scanner.lookAhead(callback)
1978                : scanner.tryScan(callback);
1979
1980            Debug.assert(saveContextFlags === contextFlags);
1981
1982            // If our callback returned something 'falsy' or we're just looking ahead,
1983            // then unconditionally restore us to where we were.
1984            if (!result || speculationKind !== SpeculationKind.TryParse) {
1985                currentToken = saveToken;
1986                if (speculationKind !== SpeculationKind.Reparse) {
1987                    parseDiagnostics.length = saveParseDiagnosticsLength;
1988                }
1989                parseErrorBeforeNextFinishedNode = saveParseErrorBeforeNextFinishedNode;
1990            }
1991
1992            return result;
1993        }
1994
1995        /** Invokes the provided callback then unconditionally restores the parser to the state it
1996         * was in immediately prior to invoking the callback.  The result of invoking the callback
1997         * is returned from this function.
1998         */
1999        function lookAhead<T>(callback: () => T): T {
2000            return speculationHelper(callback, SpeculationKind.Lookahead);
2001        }
2002
2003        /** Invokes the provided callback.  If the callback returns something falsy, then it restores
2004         * the parser to the state it was in immediately prior to invoking the callback.  If the
2005         * callback returns something truthy, then the parser state is not rolled back.  The result
2006         * of invoking the callback is returned from this function.
2007         */
2008        function tryParse<T>(callback: () => T): T {
2009            return speculationHelper(callback, SpeculationKind.TryParse);
2010        }
2011
2012        function isBindingIdentifier(): boolean {
2013            if (token() === SyntaxKind.Identifier) {
2014                return true;
2015            }
2016
2017            // `let await`/`let yield` in [Yield] or [Await] are allowed here and disallowed in the binder.
2018            return token() > SyntaxKind.LastReservedWord;
2019        }
2020
2021        // Ignore strict mode flag because we will report an error in type checker instead.
2022        function isIdentifier(): boolean {
2023            if (token() === SyntaxKind.Identifier) {
2024                return true;
2025            }
2026
2027            // If we have a 'yield' keyword, and we're in the [yield] context, then 'yield' is
2028            // considered a keyword and is not an identifier.
2029            if (token() === SyntaxKind.YieldKeyword && inYieldContext()) {
2030                return false;
2031            }
2032
2033            // If we have a 'await' keyword, and we're in the [Await] context, then 'await' is
2034            // considered a keyword and is not an identifier.
2035            if (token() === SyntaxKind.AwaitKeyword && inAwaitContext()) {
2036                return false;
2037            }
2038
2039            return token() > SyntaxKind.LastReservedWord;
2040        }
2041
2042        function parseExpected(kind: SyntaxKind, diagnosticMessage?: DiagnosticMessage, shouldAdvance = true): boolean {
2043            if (token() === kind) {
2044                if (shouldAdvance) {
2045                    nextToken();
2046                }
2047                return true;
2048            }
2049
2050            if (token() !== kind && stateStylesRootNode && inEtsStateStylesContext()) {
2051                return true;
2052            }
2053
2054            // Report specific message if provided with one.  Otherwise, report generic fallback message.
2055            if (diagnosticMessage) {
2056                parseErrorAtCurrentToken(diagnosticMessage);
2057            }
2058            else {
2059                parseErrorAtCurrentToken(Diagnostics._0_expected, tokenToString(kind));
2060            }
2061            return false;
2062        }
2063
2064        const viableKeywordSuggestions = Object.keys(textToKeywordObj).filter(keyword => keyword.length > 2);
2065
2066        /**
2067         * Provides a better error message than the generic "';' expected" if possible for
2068         * known common variants of a missing semicolon, such as from a mispelled names.
2069         *
2070         * @param node Node preceding the expected semicolon location.
2071         */
2072        function parseErrorForMissingSemicolonAfter(node: Expression | PropertyName): void {
2073            // Tagged template literals are sometimes used in places where only simple strings are allowed, i.e.:
2074            //   module `M1` {
2075            //   ^^^^^^^^^^^ This block is parsed as a template literal like module`M1`.
2076            if (isTaggedTemplateExpression(node)) {
2077                parseErrorAt(skipTrivia(sourceText, node.template.pos), node.template.end, Diagnostics.Module_declaration_names_may_only_use_or_quoted_strings);
2078                return;
2079            }
2080
2081            // Otherwise, if this isn't a well-known keyword-like identifier, give the generic fallback message.
2082            const expressionText = ts.isIdentifier(node) ? idText(node) : undefined;
2083            if (!expressionText || !isIdentifierText(expressionText, languageVersion)) {
2084                parseErrorAtCurrentToken(Diagnostics._0_expected, tokenToString(SyntaxKind.SemicolonToken));
2085                return;
2086            }
2087
2088            const pos = skipTrivia(sourceText, node.pos);
2089
2090            // Some known keywords are likely signs of syntax being used improperly.
2091            switch (expressionText) {
2092                case "const":
2093                case "let":
2094                case "var":
2095                    parseErrorAt(pos, node.end, Diagnostics.Variable_declaration_not_allowed_at_this_location);
2096                    return;
2097
2098                case "declare":
2099                    // If a declared node failed to parse, it would have emitted a diagnostic already.
2100                    return;
2101
2102                case "interface":
2103                    parseErrorForInvalidName(Diagnostics.Interface_name_cannot_be_0, Diagnostics.Interface_must_be_given_a_name, SyntaxKind.OpenBraceToken);
2104                    return;
2105
2106                case "is":
2107                    parseErrorAt(pos, scanner.getTextPos(), Diagnostics.A_type_predicate_is_only_allowed_in_return_type_position_for_functions_and_methods);
2108                    return;
2109
2110                case "module":
2111                case "namespace":
2112                    parseErrorForInvalidName(Diagnostics.Namespace_name_cannot_be_0, Diagnostics.Namespace_must_be_given_a_name, SyntaxKind.OpenBraceToken);
2113                    return;
2114
2115                case "type":
2116                    parseErrorForInvalidName(Diagnostics.Type_alias_name_cannot_be_0, Diagnostics.Type_alias_must_be_given_a_name, SyntaxKind.EqualsToken);
2117                    return;
2118            }
2119
2120            // The user alternatively might have misspelled or forgotten to add a space after a common keyword.
2121            const suggestion = getSpellingSuggestion(expressionText, viableKeywordSuggestions, n => n) ?? getSpaceSuggestion(expressionText);
2122            if (suggestion) {
2123                parseErrorAt(pos, node.end, Diagnostics.Unknown_keyword_or_identifier_Did_you_mean_0, suggestion);
2124                return;
2125            }
2126
2127            // Unknown tokens are handled with their own errors in the scanner
2128            if (token() === SyntaxKind.Unknown) {
2129                return;
2130            }
2131
2132            // Otherwise, we know this some kind of unknown word, not just a missing expected semicolon.
2133            parseErrorAt(pos, node.end, Diagnostics.Unexpected_keyword_or_identifier);
2134        }
2135
2136        /**
2137         * Reports a diagnostic error for the current token being an invalid name.
2138         *
2139         * @param blankDiagnostic Diagnostic to report for the case of the name being blank (matched tokenIfBlankName).
2140         * @param nameDiagnostic Diagnostic to report for all other cases.
2141         * @param tokenIfBlankName Current token if the name was invalid for being blank (not provided / skipped).
2142         */
2143        function parseErrorForInvalidName(nameDiagnostic: DiagnosticMessage, blankDiagnostic: DiagnosticMessage, tokenIfBlankName: SyntaxKind) {
2144            if (token() === tokenIfBlankName) {
2145                parseErrorAtCurrentToken(blankDiagnostic);
2146            }
2147            else {
2148                parseErrorAtCurrentToken(nameDiagnostic, scanner.getTokenValue());
2149            }
2150        }
2151
2152        function getSpaceSuggestion(expressionText: string) {
2153            for (const keyword of viableKeywordSuggestions) {
2154                if (expressionText.length > keyword.length + 2 && startsWith(expressionText, keyword)) {
2155                    return `${keyword} ${expressionText.slice(keyword.length)}`;
2156                }
2157            }
2158
2159            return undefined;
2160        }
2161
2162        function parseSemicolonAfterPropertyName(name: PropertyName, type: TypeNode | undefined, initializer: Expression | undefined) {
2163            if (token() === SyntaxKind.AtToken && !scanner.hasPrecedingLineBreak()) {
2164                parseErrorAtCurrentToken(Diagnostics.Decorators_must_precede_the_name_and_all_keywords_of_property_declarations);
2165                return;
2166            }
2167
2168            if (token() === SyntaxKind.OpenParenToken) {
2169                parseErrorAtCurrentToken(Diagnostics.Cannot_start_a_function_call_in_a_type_annotation);
2170                nextToken();
2171                return;
2172            }
2173
2174            if (type && !canParseSemicolon()) {
2175                if (initializer) {
2176                    parseErrorAtCurrentToken(Diagnostics._0_expected, tokenToString(SyntaxKind.SemicolonToken));
2177                }
2178                else {
2179                    parseErrorAtCurrentToken(Diagnostics.Expected_for_property_initializer);
2180                }
2181                return;
2182            }
2183
2184            if (tryParseSemicolon()) {
2185                return;
2186            }
2187
2188            if (initializer) {
2189                parseErrorAtCurrentToken(Diagnostics._0_expected, tokenToString(SyntaxKind.SemicolonToken));
2190                return;
2191            }
2192
2193            parseErrorForMissingSemicolonAfter(name);
2194        }
2195
2196        function parseExpectedJSDoc(kind: JSDocSyntaxKind) {
2197            if (token() === kind) {
2198                nextTokenJSDoc();
2199                return true;
2200            }
2201            parseErrorAtCurrentToken(Diagnostics._0_expected, tokenToString(kind));
2202            return false;
2203        }
2204
2205        function parseExpectedMatchingBrackets(openKind: SyntaxKind, closeKind: SyntaxKind, openParsed: boolean, openPosition: number) {
2206            if (token() === closeKind) {
2207                nextToken();
2208                return;
2209            }
2210            const lastError = parseErrorAtCurrentToken(Diagnostics._0_expected, tokenToString(closeKind));
2211            if (!openParsed) {
2212                return;
2213            }
2214            if (lastError) {
2215                addRelatedInfo(
2216                    lastError,
2217                    createDetachedDiagnostic(fileName, openPosition, 1, Diagnostics.The_parser_expected_to_find_a_1_to_match_the_0_token_here, tokenToString(openKind), tokenToString(closeKind))
2218                );
2219            }
2220        }
2221
2222        function parseOptional(t: SyntaxKind): boolean {
2223            if (token() === t) {
2224                nextToken();
2225                return true;
2226            }
2227            return false;
2228        }
2229
2230        function parseOptionalToken<TKind extends SyntaxKind>(t: TKind): Token<TKind>;
2231        function parseOptionalToken(t: SyntaxKind): Node | undefined {
2232            if (token() === t) {
2233                return parseTokenNode();
2234            }
2235            return undefined;
2236        }
2237
2238        function parseOptionalTokenJSDoc<TKind extends JSDocSyntaxKind>(t: TKind): Token<TKind>;
2239        function parseOptionalTokenJSDoc(t: JSDocSyntaxKind): Node | undefined {
2240            if (token() === t) {
2241                return parseTokenNodeJSDoc();
2242            }
2243            return undefined;
2244        }
2245
2246        function parseExpectedToken<TKind extends SyntaxKind>(t: TKind, diagnosticMessage?: DiagnosticMessage, arg0?: any): Token<TKind>;
2247        function parseExpectedToken(t: SyntaxKind, diagnosticMessage?: DiagnosticMessage, arg0?: any): Node {
2248            return parseOptionalToken(t) ||
2249                createMissingNode(t, /*reportAtCurrentPosition*/ false, diagnosticMessage || Diagnostics._0_expected, arg0 || tokenToString(t));
2250        }
2251
2252        function parseExpectedTokenJSDoc<TKind extends JSDocSyntaxKind>(t: TKind): Token<TKind>;
2253        function parseExpectedTokenJSDoc(t: JSDocSyntaxKind): Node {
2254            return parseOptionalTokenJSDoc(t) ||
2255                createMissingNode(t, /*reportAtCurrentPosition*/ false, Diagnostics._0_expected, tokenToString(t));
2256        }
2257
2258        function parseTokenNode<T extends Node>(): T {
2259            const pos = getNodePos();
2260            const kind = token();
2261            nextToken();
2262            return finishNode(factory.createToken(kind), pos) as T;
2263        }
2264
2265        function parseTokenNodeJSDoc<T extends Node>(): T {
2266            const pos = getNodePos();
2267            const kind = token();
2268            nextTokenJSDoc();
2269            return finishNode(factory.createToken(kind), pos) as T;
2270        }
2271
2272        function canParseSemicolon() {
2273            // If there's a real semicolon, then we can always parse it out.
2274            if (token() === SyntaxKind.SemicolonToken) {
2275                return true;
2276            }
2277
2278            // We can parse out an optional semicolon in ASI cases in the following cases.
2279            return token() === SyntaxKind.CloseBraceToken || token() === SyntaxKind.EndOfFileToken || scanner.hasPrecedingLineBreak();
2280        }
2281
2282        function tryParseSemicolon() {
2283            if (!canParseSemicolon()) {
2284                return false;
2285            }
2286
2287            if (token() === SyntaxKind.SemicolonToken) {
2288                // consume the semicolon if it was explicitly provided.
2289                nextToken();
2290            }
2291
2292            return true;
2293        }
2294
2295        function parseSemicolon(): boolean {
2296            return tryParseSemicolon() || parseExpected(SyntaxKind.SemicolonToken);
2297        }
2298
2299        function createNodeArray<T extends Node>(elements: T[], pos: number, end?: number, hasTrailingComma?: boolean): NodeArray<T> {
2300            const array = factory.createNodeArray(elements, hasTrailingComma);
2301            setTextRangePosEnd(array, pos, end ?? scanner.getStartPos());
2302            return array;
2303        }
2304
2305        function finishNode<T extends Node>(node: T, pos: number, end?: number, virtual?: boolean): T {
2306            setTextRangePosEnd(node, pos, end ?? scanner.getStartPos());
2307            if (contextFlags) {
2308                (node as Mutable<T>).flags |= contextFlags;
2309            }
2310
2311            // Keep track on the node if we encountered an error while parsing it.  If we did, then
2312            // we cannot reuse the node incrementally.  Once we've marked this node, clear out the
2313            // flag so that we don't mark any subsequent nodes.
2314            if (parseErrorBeforeNextFinishedNode) {
2315                parseErrorBeforeNextFinishedNode = false;
2316                (node as Mutable<T>).flags |= NodeFlags.ThisNodeHasError;
2317            }
2318
2319            if (virtual) {
2320                node.virtual = true;
2321            }
2322
2323            return node;
2324        }
2325
2326        function createMissingNode<T extends Node>(kind: T["kind"], reportAtCurrentPosition: false, diagnosticMessage?: DiagnosticMessage, arg0?: any): T;
2327        function createMissingNode<T extends Node>(kind: T["kind"], reportAtCurrentPosition: boolean, diagnosticMessage: DiagnosticMessage, arg0?: any): T;
2328        function createMissingNode<T extends Node>(kind: T["kind"], reportAtCurrentPosition: boolean, diagnosticMessage: DiagnosticMessage, arg0?: any): T {
2329            if (reportAtCurrentPosition) {
2330                parseErrorAtPosition(scanner.getStartPos(), 0, diagnosticMessage, arg0);
2331            }
2332            else if (diagnosticMessage) {
2333                parseErrorAtCurrentToken(diagnosticMessage, arg0);
2334            }
2335
2336            const pos = getNodePos();
2337            const result =
2338                kind === SyntaxKind.Identifier ? factory.createIdentifier("", /*typeArguments*/ undefined, /*originalKeywordKind*/ undefined) :
2339                isTemplateLiteralKind(kind) ? factory.createTemplateLiteralLikeNode(kind, "", "", /*templateFlags*/ undefined) :
2340                kind === SyntaxKind.NumericLiteral ? factory.createNumericLiteral("", /*numericLiteralFlags*/ undefined) :
2341                kind === SyntaxKind.StringLiteral ? factory.createStringLiteral("", /*isSingleQuote*/ undefined) :
2342                kind === SyntaxKind.MissingDeclaration ? factory.createMissingDeclaration() :
2343                factory.createToken(kind);
2344            return finishNode(result, pos) as T;
2345        }
2346
2347        function internIdentifier(text: string): string {
2348            let identifier = identifiers.get(text);
2349            if (identifier === undefined) {
2350                identifiers.set(text, identifier = text);
2351            }
2352            return identifier;
2353        }
2354
2355        // An identifier that starts with two underscores has an extra underscore character prepended to it to avoid issues
2356        // with magic property names like '__proto__'. The 'identifiers' object is used to share a single string instance for
2357        // each identifier in order to reduce memory consumption.
2358        function createIdentifier(isIdentifier: boolean, diagnosticMessage?: DiagnosticMessage, privateIdentifierDiagnosticMessage?: DiagnosticMessage): Identifier {
2359            if (isIdentifier) {
2360                identifierCount++;
2361                const pos = getNodePos();
2362                // Store original token kind if it is not just an Identifier so we can report appropriate error later in type checker
2363                const originalKeywordKind = token();
2364                const text = internIdentifier(scanner.getTokenValue());
2365                const hasExtendedUnicodeEscape = scanner.hasExtendedUnicodeEscape();
2366                nextTokenWithoutCheck();
2367                return finishNode(factory.createIdentifier(text, /*typeArguments*/ undefined, originalKeywordKind, hasExtendedUnicodeEscape), pos);
2368            }
2369
2370            if (token() === SyntaxKind.PrivateIdentifier) {
2371                parseErrorAtCurrentToken(privateIdentifierDiagnosticMessage || Diagnostics.Private_identifiers_are_not_allowed_outside_class_bodies);
2372                return createIdentifier(/*isIdentifier*/ true);
2373            }
2374
2375            if (token() === SyntaxKind.Unknown && scanner.tryScan(() => scanner.reScanInvalidIdentifier() === SyntaxKind.Identifier)) {
2376                // Scanner has already recorded an 'Invalid character' error, so no need to add another from the parser.
2377                return createIdentifier(/*isIdentifier*/ true);
2378            }
2379
2380            if (stateStylesRootNode && inEtsStateStylesContext() && token() === SyntaxKind.DotToken) {
2381                identifierCount++;
2382                const pos = getNodePos();
2383                return finishVirtualNode(
2384                    factory.createIdentifier(`${stateStylesRootNode}Instance`, /*typeArguments*/ undefined, SyntaxKind.Identifier),
2385                    pos,
2386                    pos
2387                );
2388            }
2389
2390            identifierCount++;
2391            // Only for end of file because the error gets reported incorrectly on embedded script tags.
2392            const reportAtCurrentPosition = token() === SyntaxKind.EndOfFileToken;
2393
2394            const isReservedWord = scanner.isReservedWord();
2395            const msgArg = scanner.getTokenText();
2396
2397            const defaultMessage = isReservedWord ?
2398                Diagnostics.Identifier_expected_0_is_a_reserved_word_that_cannot_be_used_here :
2399                Diagnostics.Identifier_expected;
2400
2401            return createMissingNode<Identifier>(SyntaxKind.Identifier, reportAtCurrentPosition, diagnosticMessage || defaultMessage, msgArg);
2402        }
2403
2404        function parseBindingIdentifier(privateIdentifierDiagnosticMessage?: DiagnosticMessage) {
2405            return createIdentifier(isBindingIdentifier(), /*diagnosticMessage*/ undefined, privateIdentifierDiagnosticMessage);
2406        }
2407
2408        function parseIdentifier(diagnosticMessage?: DiagnosticMessage, privateIdentifierDiagnosticMessage?: DiagnosticMessage): Identifier {
2409            return createIdentifier(isIdentifier(), diagnosticMessage, privateIdentifierDiagnosticMessage);
2410        }
2411
2412        function parseEtsIdentifier(pos: number): Identifier {
2413            identifierCount++;
2414            const text = internIdentifier(stylesEtsComponentDeclaration!.type);
2415            return finishVirtualNode(factory.createIdentifier(text), pos, pos);
2416        }
2417
2418        function parseIdentifierName(diagnosticMessage?: DiagnosticMessage): Identifier {
2419            return createIdentifier(tokenIsIdentifierOrKeyword(token()), diagnosticMessage);
2420        }
2421
2422        function isLiteralPropertyName(): boolean {
2423            return tokenIsIdentifierOrKeyword(token()) ||
2424                token() === SyntaxKind.StringLiteral ||
2425                token() === SyntaxKind.NumericLiteral;
2426        }
2427
2428        function isAssertionKey(): boolean {
2429            return tokenIsIdentifierOrKeyword(token()) ||
2430                token() === SyntaxKind.StringLiteral;
2431        }
2432
2433        function parsePropertyNameWorker(allowComputedPropertyNames: boolean): PropertyName {
2434            if (token() === SyntaxKind.StringLiteral || token() === SyntaxKind.NumericLiteral) {
2435                const node = parseLiteralNode() as StringLiteral | NumericLiteral;
2436                node.text = internIdentifier(node.text);
2437                return node;
2438            }
2439            if (allowComputedPropertyNames && token() === SyntaxKind.OpenBracketToken) {
2440                return parseComputedPropertyName();
2441            }
2442            if (token() === SyntaxKind.PrivateIdentifier) {
2443                return parsePrivateIdentifier();
2444            }
2445            return parseIdentifierName();
2446        }
2447
2448        function parsePropertyName(): PropertyName {
2449            return parsePropertyNameWorker(/*allowComputedPropertyNames*/ true);
2450        }
2451
2452        function parseComputedPropertyName(): ComputedPropertyName {
2453            // PropertyName [Yield]:
2454            //      LiteralPropertyName
2455            //      ComputedPropertyName[?Yield]
2456            const pos = getNodePos();
2457            parseExpected(SyntaxKind.OpenBracketToken);
2458            // We parse any expression (including a comma expression). But the grammar
2459            // says that only an assignment expression is allowed, so the grammar checker
2460            // will error if it sees a comma expression.
2461            const expression = allowInAnd(parseExpression);
2462            parseExpected(SyntaxKind.CloseBracketToken);
2463            return finishNode(factory.createComputedPropertyName(expression), pos);
2464        }
2465
2466        function internPrivateIdentifier(text: string): string {
2467            let privateIdentifier = privateIdentifiers.get(text);
2468            if (privateIdentifier === undefined) {
2469                privateIdentifiers.set(text, privateIdentifier = text);
2470            }
2471            return privateIdentifier;
2472        }
2473
2474        function parsePrivateIdentifier(): PrivateIdentifier {
2475            const pos = getNodePos();
2476            const node = factory.createPrivateIdentifier(internPrivateIdentifier(scanner.getTokenValue()));
2477            nextToken();
2478            return finishNode(node, pos);
2479        }
2480
2481        function parseContextualModifier(t: SyntaxKind): boolean {
2482            return token() === t && tryParse(nextTokenCanFollowModifier);
2483        }
2484
2485        function nextTokenIsOnSameLineAndCanFollowModifier() {
2486            nextToken();
2487            if (scanner.hasPrecedingLineBreak()) {
2488                return false;
2489            }
2490            return canFollowModifier();
2491        }
2492
2493        function nextTokenCanFollowModifier() {
2494            switch (token()) {
2495                case SyntaxKind.ConstKeyword:
2496                    // 'const' is only a modifier if followed by 'enum'.
2497                    return nextToken() === SyntaxKind.EnumKeyword;
2498                case SyntaxKind.ExportKeyword:
2499                    nextToken();
2500                    if (token() === SyntaxKind.DefaultKeyword) {
2501                        return lookAhead(nextTokenCanFollowDefaultKeyword);
2502                    }
2503                    if (token() === SyntaxKind.TypeKeyword) {
2504                        return lookAhead(nextTokenCanFollowExportModifier);
2505                    }
2506                    if (inEtsAnnotationContext() && token() === SyntaxKind.AtToken) {
2507                        return lookAhead(() => nextToken() === SyntaxKind.InterfaceKeyword);
2508                    }
2509                    return canFollowExportModifier();
2510                case SyntaxKind.DefaultKeyword:
2511                    return nextTokenCanFollowDefaultKeyword();
2512                case SyntaxKind.AccessorKeyword:
2513                case SyntaxKind.StaticKeyword:
2514                case SyntaxKind.GetKeyword:
2515                case SyntaxKind.SetKeyword:
2516                    nextToken();
2517                    return canFollowModifier();
2518                default:
2519                    return nextTokenIsOnSameLineAndCanFollowModifier();
2520            }
2521        }
2522
2523        function canFollowExportModifier(): boolean {
2524            return token() !== SyntaxKind.AsteriskToken
2525                && token() !== SyntaxKind.AsKeyword
2526                && token() !== SyntaxKind.OpenBraceToken
2527                && canFollowModifier();
2528        }
2529
2530        function nextTokenCanFollowExportModifier(): boolean {
2531            nextToken();
2532            return canFollowExportModifier();
2533        }
2534
2535        function parseAnyContextualModifier(): boolean {
2536            return isModifierKind(token()) && tryParse(nextTokenCanFollowModifier);
2537        }
2538
2539        function canFollowModifier(): boolean {
2540            return token() === SyntaxKind.OpenBracketToken
2541                || token() === SyntaxKind.OpenBraceToken
2542                || token() === SyntaxKind.AsteriskToken
2543                || token() === SyntaxKind.DotDotDotToken
2544                || token() === SyntaxKind.AtToken && inEtsAnnotationContext() && lookAhead(() => nextToken() === SyntaxKind.InterfaceKeyword)
2545                || isLiteralPropertyName();
2546        }
2547
2548        function nextTokenCanFollowDefaultKeyword(): boolean {
2549            nextToken();
2550            return token() === SyntaxKind.ClassKeyword || (inEtsContext() && token() === SyntaxKind.StructKeyword) ||
2551                token() === SyntaxKind.FunctionKeyword || token() === SyntaxKind.InterfaceKeyword ||
2552                (token() === SyntaxKind.AbstractKeyword && lookAhead(nextTokenIsClassKeywordOnSameLine)) ||
2553                (token() === SyntaxKind.AsyncKeyword && lookAhead(nextTokenIsFunctionKeywordOnSameLine));
2554        }
2555
2556        // True if positioned at the start of a list element
2557        function isListElement(parsingContext: ParsingContext, inErrorRecovery: boolean): boolean {
2558            const node = currentNode(parsingContext);
2559            if (node) {
2560                return true;
2561            }
2562
2563            switch (parsingContext) {
2564                case ParsingContext.SourceElements:
2565                case ParsingContext.BlockStatements:
2566                case ParsingContext.SwitchClauseStatements:
2567                    // If we're in error recovery, then we don't want to treat ';' as an empty statement.
2568                    // The problem is that ';' can show up in far too many contexts, and if we see one
2569                    // and assume it's a statement, then we may bail out inappropriately from whatever
2570                    // we're parsing.  For example, if we have a semicolon in the middle of a class, then
2571                    // we really don't want to assume the class is over and we're on a statement in the
2572                    // outer module.  We just want to consume and move on.
2573                    return !(token() === SyntaxKind.SemicolonToken && inErrorRecovery) && isStartOfStatement();
2574                case ParsingContext.SwitchClauses:
2575                    return token() === SyntaxKind.CaseKeyword || token() === SyntaxKind.DefaultKeyword;
2576                case ParsingContext.TypeMembers:
2577                    return lookAhead(isTypeMemberStart);
2578                case ParsingContext.ClassMembers:
2579                    // We allow semicolons as class elements (as specified by ES6) as long as we're
2580                    // not in error recovery.  If we're in error recovery, we don't want an errant
2581                    // semicolon to be treated as a class member (since they're almost always used
2582                    // for statements.
2583                    return lookAhead(isClassMemberStart) || (token() === SyntaxKind.SemicolonToken && !inErrorRecovery);
2584                case ParsingContext.AnnotationMembers:
2585                    return lookAhead(isAnnotationMemberStart);
2586                case ParsingContext.EnumMembers:
2587                    // Include open bracket computed properties. This technically also lets in indexers,
2588                    // which would be a candidate for improved error reporting.
2589                    return token() === SyntaxKind.OpenBracketToken || isLiteralPropertyName();
2590                case ParsingContext.ObjectLiteralMembers:
2591                    switch (token()) {
2592                        case SyntaxKind.OpenBracketToken:
2593                        case SyntaxKind.AsteriskToken:
2594                        case SyntaxKind.DotDotDotToken:
2595                        case SyntaxKind.DotToken: // Not an object literal member, but don't want to close the object (see `tests/cases/fourslash/completionsDotInObjectLiteral.ts`)
2596                            return true;
2597                        default:
2598                            return isLiteralPropertyName();
2599                    }
2600                case ParsingContext.RestProperties:
2601                    return isLiteralPropertyName();
2602                case ParsingContext.ObjectBindingElements:
2603                    return token() === SyntaxKind.OpenBracketToken || token() === SyntaxKind.DotDotDotToken || isLiteralPropertyName();
2604                case ParsingContext.AssertEntries:
2605                    return isAssertionKey();
2606                case ParsingContext.HeritageClauseElement:
2607                    // If we see `{ ... }` then only consume it as an expression if it is followed by `,` or `{`
2608                    // That way we won't consume the body of a class in its heritage clause.
2609                    if (token() === SyntaxKind.OpenBraceToken) {
2610                        return lookAhead(isValidHeritageClauseObjectLiteral);
2611                    }
2612
2613                    if (!inErrorRecovery) {
2614                        return isStartOfLeftHandSideExpression() && !isHeritageClauseExtendsOrImplementsKeyword();
2615                    }
2616                    else {
2617                        // If we're in error recovery we tighten up what we're willing to match.
2618                        // That way we don't treat something like "this" as a valid heritage clause
2619                        // element during recovery.
2620                        return isIdentifier() && !isHeritageClauseExtendsOrImplementsKeyword();
2621                    }
2622                case ParsingContext.VariableDeclarations:
2623                    return isBindingIdentifierOrPrivateIdentifierOrPattern();
2624                case ParsingContext.ArrayBindingElements:
2625                    return token() === SyntaxKind.CommaToken || token() === SyntaxKind.DotDotDotToken || isBindingIdentifierOrPrivateIdentifierOrPattern();
2626                case ParsingContext.TypeParameters:
2627                    return token() === SyntaxKind.InKeyword || isIdentifier();
2628                case ParsingContext.ArrayLiteralMembers:
2629                    switch (token()) {
2630                        case SyntaxKind.CommaToken:
2631                        case SyntaxKind.DotToken: // Not an array literal member, but don't want to close the array (see `tests/cases/fourslash/completionsDotInArrayLiteralInObjectLiteral.ts`)
2632                            return true;
2633                    }
2634                    // falls through
2635                case ParsingContext.ArgumentExpressions:
2636                    return token() === SyntaxKind.DotDotDotToken || isStartOfExpression();
2637                case ParsingContext.Parameters:
2638                    return isStartOfParameter(/*isJSDocParameter*/ false);
2639                case ParsingContext.JSDocParameters:
2640                    return isStartOfParameter(/*isJSDocParameter*/ true);
2641                case ParsingContext.TypeArguments:
2642                case ParsingContext.TupleElementTypes:
2643                    return token() === SyntaxKind.CommaToken || isStartOfType();
2644                case ParsingContext.HeritageClauses:
2645                    return isHeritageClause();
2646                case ParsingContext.ImportOrExportSpecifiers:
2647                    return tokenIsIdentifierOrKeyword(token());
2648                case ParsingContext.JsxAttributes:
2649                    return tokenIsIdentifierOrKeyword(token()) || token() === SyntaxKind.OpenBraceToken;
2650                case ParsingContext.JsxChildren:
2651                    return true;
2652            }
2653
2654            return Debug.fail("Non-exhaustive case in 'isListElement'.");
2655        }
2656
2657        function isValidHeritageClauseObjectLiteral() {
2658            Debug.assert(token() === SyntaxKind.OpenBraceToken);
2659            if (nextToken() === SyntaxKind.CloseBraceToken) {
2660                // if we see "extends {}" then only treat the {} as what we're extending (and not
2661                // the class body) if we have:
2662                //
2663                //      extends {} {
2664                //      extends {},
2665                //      extends {} extends
2666                //      extends {} implements
2667
2668                const next = nextToken();
2669                return next === SyntaxKind.CommaToken || next === SyntaxKind.OpenBraceToken || next === SyntaxKind.ExtendsKeyword || next === SyntaxKind.ImplementsKeyword;
2670            }
2671
2672            return true;
2673        }
2674
2675        function nextTokenIsIdentifier() {
2676            nextToken();
2677            return isIdentifier();
2678        }
2679
2680        function nextTokenIsIdentifierOrKeyword() {
2681            nextToken();
2682            return tokenIsIdentifierOrKeyword(token());
2683        }
2684
2685        function nextTokenIsIdentifierOrKeywordOrGreaterThan() {
2686            nextToken();
2687            return tokenIsIdentifierOrKeywordOrGreaterThan(token());
2688        }
2689
2690        function isHeritageClauseExtendsOrImplementsKeyword(): boolean {
2691            if (token() === SyntaxKind.ImplementsKeyword ||
2692                token() === SyntaxKind.ExtendsKeyword) {
2693
2694                return lookAhead(nextTokenIsStartOfExpression);
2695            }
2696
2697            return false;
2698        }
2699
2700        function nextTokenIsStartOfExpression() {
2701            nextToken();
2702            return isStartOfExpression();
2703        }
2704
2705        function nextTokenIsStartOfType() {
2706            nextToken();
2707            return isStartOfType();
2708        }
2709
2710        // True if positioned at a list terminator
2711        function isListTerminator(kind: ParsingContext): boolean {
2712            if (token() === SyntaxKind.EndOfFileToken) {
2713                // Being at the end of the file ends all lists.
2714                return true;
2715            }
2716
2717            switch (kind) {
2718                case ParsingContext.BlockStatements:
2719                case ParsingContext.SwitchClauses:
2720                case ParsingContext.TypeMembers:
2721                case ParsingContext.ClassMembers:
2722                case ParsingContext.AnnotationMembers:
2723                case ParsingContext.EnumMembers:
2724                case ParsingContext.ObjectLiteralMembers:
2725                case ParsingContext.ObjectBindingElements:
2726                case ParsingContext.ImportOrExportSpecifiers:
2727                case ParsingContext.AssertEntries:
2728                    return token() === SyntaxKind.CloseBraceToken;
2729                case ParsingContext.SwitchClauseStatements:
2730                    return token() === SyntaxKind.CloseBraceToken || token() === SyntaxKind.CaseKeyword || token() === SyntaxKind.DefaultKeyword;
2731                case ParsingContext.HeritageClauseElement:
2732                    return token() === SyntaxKind.OpenBraceToken || token() === SyntaxKind.ExtendsKeyword || token() === SyntaxKind.ImplementsKeyword;
2733                case ParsingContext.VariableDeclarations:
2734                    return isVariableDeclaratorListTerminator();
2735                case ParsingContext.TypeParameters:
2736                    // Tokens other than '>' are here for better error recovery
2737                    return token() === SyntaxKind.GreaterThanToken || token() === SyntaxKind.OpenParenToken || token() === SyntaxKind.OpenBraceToken || token() === SyntaxKind.ExtendsKeyword || token() === SyntaxKind.ImplementsKeyword;
2738                case ParsingContext.ArgumentExpressions:
2739                    // Tokens other than ')' are here for better error recovery
2740                    return token() === SyntaxKind.CloseParenToken || token() === SyntaxKind.SemicolonToken;
2741                case ParsingContext.ArrayLiteralMembers:
2742                case ParsingContext.TupleElementTypes:
2743                case ParsingContext.ArrayBindingElements:
2744                    return token() === SyntaxKind.CloseBracketToken;
2745                case ParsingContext.JSDocParameters:
2746                case ParsingContext.Parameters:
2747                case ParsingContext.RestProperties:
2748                    // Tokens other than ')' and ']' (the latter for index signatures) are here for better error recovery
2749                    return token() === SyntaxKind.CloseParenToken || token() === SyntaxKind.CloseBracketToken /*|| token === SyntaxKind.OpenBraceToken*/;
2750                case ParsingContext.TypeArguments:
2751                    // All other tokens should cause the type-argument to terminate except comma token
2752                    return token() !== SyntaxKind.CommaToken;
2753                case ParsingContext.HeritageClauses:
2754                    return token() === SyntaxKind.OpenBraceToken || token() === SyntaxKind.CloseBraceToken;
2755                case ParsingContext.JsxAttributes:
2756                    return token() === SyntaxKind.GreaterThanToken || token() === SyntaxKind.SlashToken;
2757                case ParsingContext.JsxChildren:
2758                    return token() === SyntaxKind.LessThanToken && lookAhead(nextTokenIsSlash);
2759                default:
2760                    return false;
2761            }
2762        }
2763
2764        function isVariableDeclaratorListTerminator(): boolean {
2765            // If we can consume a semicolon (either explicitly, or with ASI), then consider us done
2766            // with parsing the list of variable declarators.
2767            if (canParseSemicolon()) {
2768                return true;
2769            }
2770
2771            // in the case where we're parsing the variable declarator of a 'for-in' statement, we
2772            // are done if we see an 'in' keyword in front of us. Same with for-of
2773            if (isInOrOfKeyword(token())) {
2774                return true;
2775            }
2776
2777            // ERROR RECOVERY TWEAK:
2778            // For better error recovery, if we see an '=>' then we just stop immediately.  We've got an
2779            // arrow function here and it's going to be very unlikely that we'll resynchronize and get
2780            // another variable declaration.
2781            if (token() === SyntaxKind.EqualsGreaterThanToken) {
2782                return true;
2783            }
2784
2785            // Keep trying to parse out variable declarators.
2786            return false;
2787        }
2788
2789        // True if positioned at element or terminator of the current list or any enclosing list
2790        function isInSomeParsingContext(): boolean {
2791            for (let kind = 0; kind < ParsingContext.Count; kind++) {
2792                if (parsingContext & (1 << kind)) {
2793                    if (isListElement(kind, /*inErrorRecovery*/ true) || isListTerminator(kind)) {
2794                        return true;
2795                    }
2796                }
2797            }
2798
2799            return false;
2800        }
2801
2802        // Parses a list of elements
2803        function parseList<T extends Node>(kind: ParsingContext, parseElement: () => T): NodeArray<T> {
2804            const saveParsingContext = parsingContext;
2805            parsingContext |= 1 << kind;
2806            const list = [];
2807            const listPos = getNodePos();
2808
2809            while (!isListTerminator(kind)) {
2810                if (isListElement(kind, /*inErrorRecovery*/ false)) {
2811                    list.push(parseListElement(kind, parseElement));
2812                    continue;
2813                }
2814
2815                if (abortParsingListOrMoveToNextToken(kind)) {
2816                    break;
2817                }
2818            }
2819
2820            parsingContext = saveParsingContext;
2821            return createNodeArray(list, listPos);
2822        }
2823
2824        function parseListElement<T extends Node | undefined>(parsingContext: ParsingContext, parseElement: () => T): T {
2825            const node = currentNode(parsingContext);
2826            if (node) {
2827                return consumeNode(node) as T;
2828            }
2829
2830            return parseElement();
2831        }
2832
2833        function currentNode(parsingContext: ParsingContext, pos?: number): Node | undefined {
2834            // If we don't have a cursor or the parsing context isn't reusable, there's nothing to reuse.
2835            //
2836            // If there is an outstanding parse error that we've encountered, but not attached to
2837            // some node, then we cannot get a node from the old source tree.  This is because we
2838            // want to mark the next node we encounter as being unusable.
2839            //
2840            // Note: This may be too conservative.  Perhaps we could reuse the node and set the bit
2841            // on it (or its leftmost child) as having the error.  For now though, being conservative
2842            // is nice and likely won't ever affect perf.
2843            if (!syntaxCursor || !isReusableParsingContext(parsingContext) || parseErrorBeforeNextFinishedNode) {
2844                return undefined;
2845            }
2846
2847            const node = syntaxCursor.currentNode(pos ?? scanner.getStartPos());
2848
2849            // Can't reuse a missing node.
2850            // Can't reuse a node that intersected the change range.
2851            // Can't reuse a node that contains a parse error.  This is necessary so that we
2852            // produce the same set of errors again.
2853            if (nodeIsMissing(node) || node.intersectsChange || containsParseError(node)) {
2854                return undefined;
2855            }
2856
2857            // We can only reuse a node if it was parsed under the same strict mode that we're
2858            // currently in.  i.e. if we originally parsed a node in non-strict mode, but then
2859            // the user added 'using strict' at the top of the file, then we can't use that node
2860            // again as the presence of strict mode may cause us to parse the tokens in the file
2861            // differently.
2862            //
2863            // Note: we *can* reuse tokens when the strict mode changes.  That's because tokens
2864            // are unaffected by strict mode.  It's just the parser will decide what to do with it
2865            // differently depending on what mode it is in.
2866            //
2867            // This also applies to all our other context flags as well.
2868            const nodeContextFlags = node.flags & NodeFlags.ContextFlags;
2869            if (nodeContextFlags !== contextFlags) {
2870                return undefined;
2871            }
2872
2873            // Ok, we have a node that looks like it could be reused.  Now verify that it is valid
2874            // in the current list parsing context that we're currently at.
2875            if (!canReuseNode(node, parsingContext)) {
2876                return undefined;
2877            }
2878
2879            if ((node as JSDocContainer).jsDocCache) {
2880                // jsDocCache may include tags from parent nodes, which might have been modified.
2881                (node as JSDocContainer).jsDocCache = undefined;
2882            }
2883
2884            return node;
2885        }
2886
2887        function consumeNode(node: Node) {
2888            // Move the scanner so it is after the node we just consumed.
2889            scanner.setTextPos(node.end);
2890            nextToken();
2891            return node;
2892        }
2893
2894        function isReusableParsingContext(parsingContext: ParsingContext): boolean {
2895            switch (parsingContext) {
2896                case ParsingContext.ClassMembers:
2897                case ParsingContext.SwitchClauses:
2898                case ParsingContext.SourceElements:
2899                case ParsingContext.BlockStatements:
2900                case ParsingContext.SwitchClauseStatements:
2901                case ParsingContext.EnumMembers:
2902                case ParsingContext.TypeMembers:
2903                case ParsingContext.VariableDeclarations:
2904                case ParsingContext.JSDocParameters:
2905                case ParsingContext.Parameters:
2906                    return true;
2907            }
2908            return false;
2909        }
2910
2911        function canReuseNode(node: Node, parsingContext: ParsingContext): boolean {
2912            switch (parsingContext) {
2913                case ParsingContext.ClassMembers:
2914                    return isReusableClassMember(node);
2915
2916                case ParsingContext.SwitchClauses:
2917                    return isReusableSwitchClause(node);
2918
2919                case ParsingContext.SourceElements:
2920                case ParsingContext.BlockStatements:
2921                case ParsingContext.SwitchClauseStatements:
2922                    return isReusableStatement(node);
2923
2924                case ParsingContext.EnumMembers:
2925                    return isReusableEnumMember(node);
2926
2927                case ParsingContext.TypeMembers:
2928                    return isReusableTypeMember(node);
2929
2930                case ParsingContext.VariableDeclarations:
2931                    return isReusableVariableDeclaration(node);
2932
2933                case ParsingContext.JSDocParameters:
2934                case ParsingContext.Parameters:
2935                    return isReusableParameter(node);
2936
2937                // Any other lists we do not care about reusing nodes in.  But feel free to add if
2938                // you can do so safely.  Danger areas involve nodes that may involve speculative
2939                // parsing.  If speculative parsing is involved with the node, then the range the
2940                // parser reached while looking ahead might be in the edited range (see the example
2941                // in canReuseVariableDeclaratorNode for a good case of this).
2942
2943                // case ParsingContext.HeritageClauses:
2944                // This would probably be safe to reuse.  There is no speculative parsing with
2945                // heritage clauses.
2946
2947                // case ParsingContext.TypeParameters:
2948                // This would probably be safe to reuse.  There is no speculative parsing with
2949                // type parameters.  Note that that's because type *parameters* only occur in
2950                // unambiguous *type* contexts.  While type *arguments* occur in very ambiguous
2951                // *expression* contexts.
2952
2953                // case ParsingContext.TupleElementTypes:
2954                // This would probably be safe to reuse.  There is no speculative parsing with
2955                // tuple types.
2956
2957                // Technically, type argument list types are probably safe to reuse.  While
2958                // speculative parsing is involved with them (since type argument lists are only
2959                // produced from speculative parsing a < as a type argument list), we only have
2960                // the types because speculative parsing succeeded.  Thus, the lookahead never
2961                // went past the end of the list and rewound.
2962                // case ParsingContext.TypeArguments:
2963
2964                // Note: these are almost certainly not safe to ever reuse.  Expressions commonly
2965                // need a large amount of lookahead, and we should not reuse them as they may
2966                // have actually intersected the edit.
2967                // case ParsingContext.ArgumentExpressions:
2968
2969                // This is not safe to reuse for the same reason as the 'AssignmentExpression'
2970                // cases.  i.e. a property assignment may end with an expression, and thus might
2971                // have lookahead far beyond it's old node.
2972                // case ParsingContext.ObjectLiteralMembers:
2973
2974                // This is probably not safe to reuse.  There can be speculative parsing with
2975                // type names in a heritage clause.  There can be generic names in the type
2976                // name list, and there can be left hand side expressions (which can have type
2977                // arguments.)
2978                // case ParsingContext.HeritageClauseElement:
2979
2980                // Perhaps safe to reuse, but it's unlikely we'd see more than a dozen attributes
2981                // on any given element. Same for children.
2982                // case ParsingContext.JsxAttributes:
2983                // case ParsingContext.JsxChildren:
2984
2985            }
2986
2987            return false;
2988        }
2989
2990        function isReusableClassMember(node: Node) {
2991            if (node) {
2992                switch (node.kind) {
2993                    case SyntaxKind.Constructor:
2994                    case SyntaxKind.IndexSignature:
2995                    case SyntaxKind.GetAccessor:
2996                    case SyntaxKind.SetAccessor:
2997                    case SyntaxKind.SemicolonClassElement:
2998                        return true;
2999                    case SyntaxKind.PropertyDeclaration:
3000                        return !inStructContext();
3001                    case SyntaxKind.MethodDeclaration:
3002                        // Method declarations are not necessarily reusable.  An object-literal
3003                        // may have a method calls "constructor(...)" and we must reparse that
3004                        // into an actual .ConstructorDeclaration.
3005                        const methodDeclaration = node as MethodDeclaration;
3006                        const nameIsConstructor = methodDeclaration.name.kind === SyntaxKind.Identifier &&
3007                            methodDeclaration.name.originalKeywordKind === SyntaxKind.ConstructorKeyword;
3008
3009                        return !nameIsConstructor;
3010                }
3011            }
3012
3013            return false;
3014        }
3015
3016        function isReusableSwitchClause(node: Node) {
3017            if (node) {
3018                switch (node.kind) {
3019                    case SyntaxKind.CaseClause:
3020                    case SyntaxKind.DefaultClause:
3021                        return true;
3022                }
3023            }
3024
3025            return false;
3026        }
3027
3028        function isReusableStatement(node: Node) {
3029            if (node) {
3030                switch (node.kind) {
3031                    case SyntaxKind.FunctionDeclaration:
3032                    case SyntaxKind.VariableStatement:
3033                    case SyntaxKind.Block:
3034                    case SyntaxKind.IfStatement:
3035                    case SyntaxKind.ExpressionStatement:
3036                    case SyntaxKind.ThrowStatement:
3037                    case SyntaxKind.ReturnStatement:
3038                    case SyntaxKind.SwitchStatement:
3039                    case SyntaxKind.BreakStatement:
3040                    case SyntaxKind.ContinueStatement:
3041                    case SyntaxKind.ForInStatement:
3042                    case SyntaxKind.ForOfStatement:
3043                    case SyntaxKind.ForStatement:
3044                    case SyntaxKind.WhileStatement:
3045                    case SyntaxKind.WithStatement:
3046                    case SyntaxKind.EmptyStatement:
3047                    case SyntaxKind.TryStatement:
3048                    case SyntaxKind.LabeledStatement:
3049                    case SyntaxKind.DoStatement:
3050                    case SyntaxKind.DebuggerStatement:
3051                    case SyntaxKind.ImportDeclaration:
3052                    case SyntaxKind.ImportEqualsDeclaration:
3053                    case SyntaxKind.ExportDeclaration:
3054                    case SyntaxKind.ExportAssignment:
3055                    case SyntaxKind.ModuleDeclaration:
3056                    case SyntaxKind.ClassDeclaration:
3057                    case SyntaxKind.StructDeclaration:
3058                    case SyntaxKind.InterfaceDeclaration:
3059                    case SyntaxKind.EnumDeclaration:
3060                    case SyntaxKind.TypeAliasDeclaration:
3061                        return true;
3062                }
3063            }
3064
3065            return false;
3066        }
3067
3068        function isReusableEnumMember(node: Node) {
3069            return node.kind === SyntaxKind.EnumMember;
3070        }
3071
3072        function isReusableTypeMember(node: Node) {
3073            if (node) {
3074                switch (node.kind) {
3075                    case SyntaxKind.ConstructSignature:
3076                    case SyntaxKind.MethodSignature:
3077                    case SyntaxKind.IndexSignature:
3078                    case SyntaxKind.PropertySignature:
3079                    case SyntaxKind.CallSignature:
3080                        return true;
3081                }
3082            }
3083
3084            return false;
3085        }
3086
3087        function isReusableVariableDeclaration(node: Node) {
3088            if (node.kind !== SyntaxKind.VariableDeclaration) {
3089                return false;
3090            }
3091
3092            // Very subtle incremental parsing bug.  Consider the following code:
3093            //
3094            //      let v = new List < A, B
3095            //
3096            // This is actually legal code.  It's a list of variable declarators "v = new List<A"
3097            // on one side and "B" on the other. If you then change that to:
3098            //
3099            //      let v = new List < A, B >()
3100            //
3101            // then we have a problem.  "v = new List<A" doesn't intersect the change range, so we
3102            // start reparsing at "B" and we completely fail to handle this properly.
3103            //
3104            // In order to prevent this, we do not allow a variable declarator to be reused if it
3105            // has an initializer.
3106            const variableDeclarator = node as VariableDeclaration;
3107            return variableDeclarator.initializer === undefined;
3108        }
3109
3110        function isReusableParameter(node: Node) {
3111            if (node.kind !== SyntaxKind.Parameter) {
3112                return false;
3113            }
3114
3115            // See the comment in isReusableVariableDeclaration for why we do this.
3116            const parameter = node as ParameterDeclaration;
3117            return parameter.initializer === undefined;
3118        }
3119
3120        // Returns true if we should abort parsing.
3121        function abortParsingListOrMoveToNextToken(kind: ParsingContext) {
3122            parsingContextErrors(kind);
3123            if (isInSomeParsingContext()) {
3124                return true;
3125            }
3126
3127            nextToken();
3128            return false;
3129        }
3130
3131        function parsingContextErrors(context: ParsingContext) {
3132            switch (context) {
3133                case ParsingContext.SourceElements:
3134                    return token() === SyntaxKind.DefaultKeyword
3135                        ? parseErrorAtCurrentToken(Diagnostics._0_expected, tokenToString(SyntaxKind.ExportKeyword))
3136                        : parseErrorAtCurrentToken(Diagnostics.Declaration_or_statement_expected);
3137                case ParsingContext.BlockStatements: return parseErrorAtCurrentToken(Diagnostics.Declaration_or_statement_expected);
3138                case ParsingContext.SwitchClauses: return parseErrorAtCurrentToken(Diagnostics.case_or_default_expected);
3139                case ParsingContext.SwitchClauseStatements: return parseErrorAtCurrentToken(Diagnostics.Statement_expected);
3140                case ParsingContext.RestProperties: // fallthrough
3141                case ParsingContext.TypeMembers: return parseErrorAtCurrentToken(Diagnostics.Property_or_signature_expected);
3142                case ParsingContext.ClassMembers: return parseErrorAtCurrentToken(Diagnostics.Unexpected_token_A_constructor_method_accessor_or_property_was_expected);
3143                case ParsingContext.AnnotationMembers: return parseErrorAtCurrentToken(Diagnostics.Unexpected_token_An_annotation_property_was_expected);
3144                case ParsingContext.EnumMembers: return parseErrorAtCurrentToken(Diagnostics.Enum_member_expected);
3145                case ParsingContext.HeritageClauseElement: return parseErrorAtCurrentToken(Diagnostics.Expression_expected);
3146                case ParsingContext.VariableDeclarations:
3147                    return isKeyword(token())
3148                        ? parseErrorAtCurrentToken(Diagnostics._0_is_not_allowed_as_a_variable_declaration_name, tokenToString(token()))
3149                        : parseErrorAtCurrentToken(Diagnostics.Variable_declaration_expected);
3150                case ParsingContext.ObjectBindingElements: return parseErrorAtCurrentToken(Diagnostics.Property_destructuring_pattern_expected);
3151                case ParsingContext.ArrayBindingElements: return parseErrorAtCurrentToken(Diagnostics.Array_element_destructuring_pattern_expected);
3152                case ParsingContext.ArgumentExpressions: return parseErrorAtCurrentToken(Diagnostics.Argument_expression_expected);
3153                case ParsingContext.ObjectLiteralMembers: return parseErrorAtCurrentToken(Diagnostics.Property_assignment_expected);
3154                case ParsingContext.ArrayLiteralMembers: return parseErrorAtCurrentToken(Diagnostics.Expression_or_comma_expected);
3155                case ParsingContext.JSDocParameters: return parseErrorAtCurrentToken(Diagnostics.Parameter_declaration_expected);
3156                case ParsingContext.Parameters:
3157                    return isKeyword(token())
3158                        ? parseErrorAtCurrentToken(Diagnostics._0_is_not_allowed_as_a_parameter_name, tokenToString(token()))
3159                        : parseErrorAtCurrentToken(Diagnostics.Parameter_declaration_expected);
3160                case ParsingContext.TypeParameters: return parseErrorAtCurrentToken(Diagnostics.Type_parameter_declaration_expected);
3161                case ParsingContext.TypeArguments: return parseErrorAtCurrentToken(Diagnostics.Type_argument_expected);
3162                case ParsingContext.TupleElementTypes: return parseErrorAtCurrentToken(Diagnostics.Type_expected);
3163                case ParsingContext.HeritageClauses: return parseErrorAtCurrentToken(Diagnostics.Unexpected_token_expected);
3164                case ParsingContext.ImportOrExportSpecifiers: return parseErrorAtCurrentToken(Diagnostics.Identifier_expected);
3165                case ParsingContext.JsxAttributes: return parseErrorAtCurrentToken(Diagnostics.Identifier_expected);
3166                case ParsingContext.JsxChildren: return parseErrorAtCurrentToken(Diagnostics.Identifier_expected);
3167                case ParsingContext.AssertEntries: return parseErrorAtCurrentToken(Diagnostics.Identifier_or_string_literal_expected); // AssertionKey.
3168                case ParsingContext.Count: return Debug.fail("ParsingContext.Count used as a context"); // Not a real context, only a marker.
3169                default: Debug.assertNever(context);
3170            }
3171        }
3172
3173        // Parses a comma-delimited list of elements
3174        function parseDelimitedList<T extends Node>(kind: ParsingContext, parseElement: () => T, considerSemicolonAsDelimiter?: boolean): NodeArray<T>;
3175        function parseDelimitedList<T extends Node | undefined>(kind: ParsingContext, parseElement: () => T, considerSemicolonAsDelimiter?: boolean): NodeArray<NonNullable<T>> | undefined;
3176        function parseDelimitedList<T extends Node | undefined>(kind: ParsingContext, parseElement: () => T, considerSemicolonAsDelimiter?: boolean): NodeArray<NonNullable<T>> | undefined {
3177            const saveParsingContext = parsingContext;
3178            parsingContext |= 1 << kind;
3179            const list: NonNullable<T>[] = [];
3180            const listPos = getNodePos();
3181
3182            let commaStart = -1; // Meaning the previous token was not a comma
3183            while (true) {
3184                if (isListElement(kind, /*inErrorRecovery*/ false)) {
3185                    const startPos = scanner.getStartPos();
3186                    const result = parseListElement(kind, parseElement);
3187                    if (!result) {
3188                        parsingContext = saveParsingContext;
3189                        return undefined;
3190                    }
3191                    list.push(result);
3192                    commaStart = scanner.getTokenPos();
3193
3194                    if (parseOptional(SyntaxKind.CommaToken)) {
3195                        // No need to check for a zero length node since we know we parsed a comma
3196                        continue;
3197                    }
3198
3199                    commaStart = -1; // Back to the state where the last token was not a comma
3200                    if (isListTerminator(kind)) {
3201                        break;
3202                    }
3203
3204                    // We didn't get a comma, and the list wasn't terminated, explicitly parse
3205                    // out a comma so we give a good error message.
3206                    parseExpected(SyntaxKind.CommaToken, getExpectedCommaDiagnostic(kind));
3207
3208                    // If the token was a semicolon, and the caller allows that, then skip it and
3209                    // continue.  This ensures we get back on track and don't result in tons of
3210                    // parse errors.  For example, this can happen when people do things like use
3211                    // a semicolon to delimit object literal members.   Note: we'll have already
3212                    // reported an error when we called parseExpected above.
3213                    if (considerSemicolonAsDelimiter && token() === SyntaxKind.SemicolonToken && !scanner.hasPrecedingLineBreak()) {
3214                        nextToken();
3215                    }
3216                    if (startPos === scanner.getStartPos()) {
3217                        // What we're parsing isn't actually remotely recognizable as a element and we've consumed no tokens whatsoever
3218                        // Consume a token to advance the parser in some way and avoid an infinite loop
3219                        // This can happen when we're speculatively parsing parenthesized expressions which we think may be arrow functions,
3220                        // or when a modifier keyword which is disallowed as a parameter name (ie, `static` in strict mode) is supplied
3221                        nextToken();
3222                    }
3223                    continue;
3224                }
3225
3226                if (isListTerminator(kind)) {
3227                    break;
3228                }
3229
3230                if (abortParsingListOrMoveToNextToken(kind)) {
3231                    break;
3232                }
3233            }
3234
3235            parsingContext = saveParsingContext;
3236            // Recording the trailing comma is deliberately done after the previous
3237            // loop, and not just if we see a list terminator. This is because the list
3238            // may have ended incorrectly, but it is still important to know if there
3239            // was a trailing comma.
3240            // Check if the last token was a comma.
3241            // Always preserve a trailing comma by marking it on the NodeArray
3242            return createNodeArray(list, listPos, /*end*/ undefined, commaStart >= 0);
3243        }
3244
3245        function getExpectedCommaDiagnostic(kind: ParsingContext) {
3246            return kind === ParsingContext.EnumMembers ? Diagnostics.An_enum_member_name_must_be_followed_by_a_or : undefined;
3247        }
3248
3249        interface MissingList<T extends Node> extends NodeArray<T> {
3250            isMissingList: true;
3251        }
3252
3253        function createMissingList<T extends Node>(): MissingList<T> {
3254            const list = createNodeArray<T>([], getNodePos()) as MissingList<T>;
3255            list.isMissingList = true;
3256            return list;
3257        }
3258
3259        function isMissingList(arr: NodeArray<Node>): boolean {
3260            return !!(arr as MissingList<Node>).isMissingList;
3261        }
3262
3263        function parseBracketedList<T extends Node>(kind: ParsingContext, parseElement: () => T, open: SyntaxKind, close: SyntaxKind): NodeArray<T> {
3264            if (parseExpected(open)) {
3265                const result = parseDelimitedList(kind, parseElement);
3266                parseExpected(close);
3267                return result;
3268            }
3269
3270            return createMissingList<T>();
3271        }
3272
3273        function parseEntityName(allowReservedWords: boolean, diagnosticMessage?: DiagnosticMessage): EntityName {
3274            const pos = getNodePos();
3275            let entity: EntityName = allowReservedWords ? parseIdentifierName(diagnosticMessage) : parseIdentifier(diagnosticMessage);
3276            let dotPos = getNodePos();
3277            while (parseOptional(SyntaxKind.DotToken)) {
3278                if (token() === SyntaxKind.LessThanToken) {
3279                    // the entity is part of a JSDoc-style generic, so record the trailing dot for later error reporting
3280                    entity.jsdocDotPos = dotPos;
3281                    break;
3282                }
3283                dotPos = getNodePos();
3284                entity = finishNode(
3285                    factory.createQualifiedName(
3286                        entity,
3287                        parseRightSideOfDot(allowReservedWords, /* allowPrivateIdentifiers */ false) as Identifier
3288                    ),
3289                    pos
3290                );
3291            }
3292            return entity;
3293        }
3294
3295        function createQualifiedName(entity: EntityName, name: Identifier): QualifiedName {
3296            return finishNode(factory.createQualifiedName(entity, name), entity.pos);
3297        }
3298
3299        function parseRightSideOfDot(allowIdentifierNames: boolean, allowPrivateIdentifiers: boolean): Identifier | PrivateIdentifier {
3300            // Technically a keyword is valid here as all identifiers and keywords are identifier names.
3301            // However, often we'll encounter this in error situations when the identifier or keyword
3302            // is actually starting another valid construct.
3303            //
3304            // So, we check for the following specific case:
3305            //
3306            //      name.
3307            //      identifierOrKeyword identifierNameOrKeyword
3308            //
3309            // Note: the newlines are important here.  For example, if that above code
3310            // were rewritten into:
3311            //
3312            //      name.identifierOrKeyword
3313            //      identifierNameOrKeyword
3314            //
3315            // Then we would consider it valid.  That's because ASI would take effect and
3316            // the code would be implicitly: "name.identifierOrKeyword; identifierNameOrKeyword".
3317            // In the first case though, ASI will not take effect because there is not a
3318            // line terminator after the identifier or keyword.
3319            if (scanner.hasPrecedingLineBreak() && tokenIsIdentifierOrKeyword(token())) {
3320                const matchesPattern = lookAhead(nextTokenIsIdentifierOrKeywordOnSameLine);
3321
3322                if (matchesPattern) {
3323                    // Report that we need an identifier.  However, report it right after the dot,
3324                    // and not on the next token.  This is because the next token might actually
3325                    // be an identifier and the error would be quite confusing.
3326                    return createMissingNode<Identifier>(SyntaxKind.Identifier, /*reportAtCurrentPosition*/ true, Diagnostics.Identifier_expected);
3327                }
3328            }
3329
3330            if (token() === SyntaxKind.PrivateIdentifier) {
3331                const node = parsePrivateIdentifier();
3332                return allowPrivateIdentifiers ? node : createMissingNode<Identifier>(SyntaxKind.Identifier, /*reportAtCurrentPosition*/ true, Diagnostics.Identifier_expected);
3333            }
3334
3335            return allowIdentifierNames ? parseIdentifierName() : parseIdentifier();
3336        }
3337
3338        function parseTemplateSpans(isTaggedTemplate: boolean) {
3339            const pos = getNodePos();
3340            const list = [];
3341            let node: TemplateSpan;
3342            do {
3343                node = parseTemplateSpan(isTaggedTemplate);
3344                list.push(node);
3345            }
3346            while (node.literal.kind === SyntaxKind.TemplateMiddle);
3347            return createNodeArray(list, pos);
3348        }
3349
3350        function parseTemplateExpression(isTaggedTemplate: boolean): TemplateExpression {
3351            const pos = getNodePos();
3352            return finishNode(
3353                factory.createTemplateExpression(
3354                    parseTemplateHead(isTaggedTemplate),
3355                    parseTemplateSpans(isTaggedTemplate)
3356                ),
3357                pos
3358            );
3359        }
3360
3361        function parseTemplateType(): TemplateLiteralTypeNode {
3362            const pos = getNodePos();
3363            return finishNode(
3364                factory.createTemplateLiteralType(
3365                    parseTemplateHead(/*isTaggedTemplate*/ false),
3366                    parseTemplateTypeSpans()
3367                ),
3368                pos
3369            );
3370        }
3371
3372        function parseTemplateTypeSpans() {
3373            const pos = getNodePos();
3374            const list = [];
3375            let node: TemplateLiteralTypeSpan;
3376            do {
3377                node = parseTemplateTypeSpan();
3378                list.push(node);
3379            }
3380            while (node.literal.kind === SyntaxKind.TemplateMiddle);
3381            return createNodeArray(list, pos);
3382        }
3383
3384        function parseTemplateTypeSpan(): TemplateLiteralTypeSpan {
3385            const pos = getNodePos();
3386            return finishNode(
3387                factory.createTemplateLiteralTypeSpan(
3388                    parseType(),
3389                    parseLiteralOfTemplateSpan(/*isTaggedTemplate*/ false)
3390                ),
3391                pos
3392            );
3393        }
3394
3395        function parseLiteralOfTemplateSpan(isTaggedTemplate: boolean) {
3396            if (token() === SyntaxKind.CloseBraceToken) {
3397                reScanTemplateToken(isTaggedTemplate);
3398                return parseTemplateMiddleOrTemplateTail();
3399            }
3400            else {
3401                // TODO(rbuckton): Do we need to call `parseExpectedToken` or can we just call `createMissingNode` directly?
3402                return parseExpectedToken(SyntaxKind.TemplateTail, Diagnostics._0_expected, tokenToString(SyntaxKind.CloseBraceToken)) as TemplateTail;
3403            }
3404        }
3405
3406        function parseTemplateSpan(isTaggedTemplate: boolean): TemplateSpan {
3407            const pos = getNodePos();
3408            return finishNode(
3409                factory.createTemplateSpan(
3410                    allowInAnd(parseExpression),
3411                    parseLiteralOfTemplateSpan(isTaggedTemplate)
3412                ),
3413                pos
3414            );
3415        }
3416
3417        function parseLiteralNode(): LiteralExpression {
3418            return parseLiteralLikeNode(token()) as LiteralExpression;
3419        }
3420
3421        function parseTemplateHead(isTaggedTemplate: boolean): TemplateHead {
3422            if (isTaggedTemplate) {
3423                reScanTemplateHeadOrNoSubstitutionTemplate();
3424            }
3425            const fragment = parseLiteralLikeNode(token());
3426            Debug.assert(fragment.kind === SyntaxKind.TemplateHead, "Template head has wrong token kind");
3427            return fragment as TemplateHead;
3428        }
3429
3430        function parseTemplateMiddleOrTemplateTail(): TemplateMiddle | TemplateTail {
3431            const fragment = parseLiteralLikeNode(token());
3432            Debug.assert(fragment.kind === SyntaxKind.TemplateMiddle || fragment.kind === SyntaxKind.TemplateTail, "Template fragment has wrong token kind");
3433            return fragment as TemplateMiddle | TemplateTail;
3434        }
3435
3436        function getTemplateLiteralRawText(kind: TemplateLiteralToken["kind"]) {
3437            const isLast = kind === SyntaxKind.NoSubstitutionTemplateLiteral || kind === SyntaxKind.TemplateTail;
3438            const tokenText = scanner.getTokenText();
3439            return tokenText.substring(1, tokenText.length - (scanner.isUnterminated() ? 0 : isLast ? 1 : 2));
3440        }
3441
3442        function parseLiteralLikeNode(kind: SyntaxKind): LiteralLikeNode {
3443            const pos = getNodePos();
3444            const node =
3445                isTemplateLiteralKind(kind) ? factory.createTemplateLiteralLikeNode(kind, scanner.getTokenValue(), getTemplateLiteralRawText(kind), scanner.getTokenFlags() & TokenFlags.TemplateLiteralLikeFlags) :
3446                // Octal literals are not allowed in strict mode or ES5
3447                // Note that theoretically the following condition would hold true literals like 009,
3448                // which is not octal. But because of how the scanner separates the tokens, we would
3449                // never get a token like this. Instead, we would get 00 and 9 as two separate tokens.
3450                // We also do not need to check for negatives because any prefix operator would be part of a
3451                // parent unary expression.
3452                kind === SyntaxKind.NumericLiteral ? factory.createNumericLiteral(scanner.getTokenValue(), scanner.getNumericLiteralFlags()) :
3453                kind === SyntaxKind.StringLiteral ? factory.createStringLiteral(scanner.getTokenValue(), /*isSingleQuote*/ undefined, scanner.hasExtendedUnicodeEscape()) :
3454                isLiteralKind(kind) ? factory.createLiteralLikeNode(kind, scanner.getTokenValue()) :
3455                Debug.fail();
3456
3457            if (scanner.hasExtendedUnicodeEscape()) {
3458                node.hasExtendedUnicodeEscape = true;
3459            }
3460
3461            if (scanner.isUnterminated()) {
3462                node.isUnterminated = true;
3463            }
3464
3465            nextToken();
3466            return finishNode(node, pos);
3467        }
3468
3469        // TYPES
3470
3471        function parseEntityNameOfTypeReference() {
3472            return parseEntityName(/*allowReservedWords*/ true, Diagnostics.Type_expected);
3473        }
3474
3475        function parseTypeArgumentsOfTypeReference() {
3476            if (!scanner.hasPrecedingLineBreak() && reScanLessThanToken() === SyntaxKind.LessThanToken) {
3477                return parseBracketedList(ParsingContext.TypeArguments, parseType, SyntaxKind.LessThanToken, SyntaxKind.GreaterThanToken);
3478            }
3479        }
3480
3481        function parseTypeReference(): TypeReferenceNode {
3482            const pos = getNodePos();
3483            return finishNode(
3484                factory.createTypeReferenceNode(
3485                    parseEntityNameOfTypeReference(),
3486                    parseTypeArgumentsOfTypeReference()
3487                ),
3488                pos
3489            );
3490        }
3491
3492        // If true, we should abort parsing an error function.
3493        function typeHasArrowFunctionBlockingParseError(node: TypeNode): boolean {
3494            switch (node.kind) {
3495                case SyntaxKind.TypeReference:
3496                    return nodeIsMissing((node as TypeReferenceNode).typeName);
3497                case SyntaxKind.FunctionType:
3498                case SyntaxKind.ConstructorType: {
3499                    const { parameters, type } = node as FunctionOrConstructorTypeNode;
3500                    return isMissingList(parameters) || typeHasArrowFunctionBlockingParseError(type);
3501                }
3502                case SyntaxKind.ParenthesizedType:
3503                    return typeHasArrowFunctionBlockingParseError((node as ParenthesizedTypeNode).type);
3504                default:
3505                    return false;
3506            }
3507        }
3508
3509        function parseThisTypePredicate(lhs: ThisTypeNode): TypePredicateNode {
3510            nextToken();
3511            return finishNode(factory.createTypePredicateNode(/*assertsModifier*/ undefined, lhs, parseType()), lhs.pos);
3512        }
3513
3514        function parseThisTypeNode(): ThisTypeNode {
3515            const pos = getNodePos();
3516            nextToken();
3517            return finishNode(factory.createThisTypeNode(), pos);
3518        }
3519
3520        function parseJSDocAllType(): JSDocAllType | JSDocOptionalType {
3521            const pos = getNodePos();
3522            nextToken();
3523            return finishNode(factory.createJSDocAllType(), pos);
3524        }
3525
3526        function parseJSDocNonNullableType(): TypeNode {
3527            const pos = getNodePos();
3528            nextToken();
3529            return finishNode(factory.createJSDocNonNullableType(parseNonArrayType(), /*postfix*/ false), pos);
3530        }
3531
3532        function parseJSDocUnknownOrNullableType(): JSDocUnknownType | JSDocNullableType {
3533            const pos = getNodePos();
3534            // skip the ?
3535            nextToken();
3536
3537            // Need to lookahead to decide if this is a nullable or unknown type.
3538
3539            // Here are cases where we'll pick the unknown type:
3540            //
3541            //      Foo(?,
3542            //      { a: ? }
3543            //      Foo(?)
3544            //      Foo<?>
3545            //      Foo(?=
3546            //      (?|
3547            if (token() === SyntaxKind.CommaToken ||
3548                token() === SyntaxKind.CloseBraceToken ||
3549                token() === SyntaxKind.CloseParenToken ||
3550                token() === SyntaxKind.GreaterThanToken ||
3551                token() === SyntaxKind.EqualsToken ||
3552                token() === SyntaxKind.BarToken) {
3553                return finishNode(factory.createJSDocUnknownType(), pos);
3554            }
3555            else {
3556                return finishNode(factory.createJSDocNullableType(parseType(), /*postfix*/ false), pos);
3557            }
3558        }
3559
3560        function parseJSDocFunctionType(): JSDocFunctionType | TypeReferenceNode {
3561            const pos = getNodePos();
3562            const hasJSDoc = hasPrecedingJSDocComment();
3563            if (lookAhead(nextTokenIsOpenParen)) {
3564                nextToken();
3565                const parameters = parseParameters(SignatureFlags.Type | SignatureFlags.JSDoc);
3566                const type = parseReturnType(SyntaxKind.ColonToken, /*isType*/ false);
3567                return withJSDoc(finishNode(factory.createJSDocFunctionType(parameters, type), pos), hasJSDoc);
3568            }
3569            return finishNode(factory.createTypeReferenceNode(parseIdentifierName(), /*typeArguments*/ undefined), pos);
3570        }
3571
3572        function parseJSDocParameter(): ParameterDeclaration {
3573            const pos = getNodePos();
3574            let name: Identifier | undefined;
3575            if (token() === SyntaxKind.ThisKeyword || token() === SyntaxKind.NewKeyword) {
3576                name = parseIdentifierName();
3577                parseExpected(SyntaxKind.ColonToken);
3578            }
3579            return finishNode(
3580                factory.createParameterDeclaration(
3581                    /*modifiers*/ undefined,
3582                    /*dotDotDotToken*/ undefined,
3583                    // TODO(rbuckton): JSDoc parameters don't have names (except `this`/`new`), should we manufacture an empty identifier?
3584                    name!,
3585                    /*questionToken*/ undefined,
3586                    parseJSDocType(),
3587                    /*initializer*/ undefined
3588                ),
3589                pos
3590            );
3591        }
3592
3593        function parseJSDocType(): TypeNode {
3594            scanner.setInJSDocType(true);
3595            const pos = getNodePos();
3596            if (parseOptional(SyntaxKind.ModuleKeyword)) {
3597                // TODO(rbuckton): We never set the type for a JSDocNamepathType. What should we put here?
3598                const moduleTag = factory.createJSDocNamepathType(/*type*/ undefined!);
3599                terminate: while (true) {
3600                    switch (token()) {
3601                        case SyntaxKind.CloseBraceToken:
3602                        case SyntaxKind.EndOfFileToken:
3603                        case SyntaxKind.CommaToken:
3604                        case SyntaxKind.WhitespaceTrivia:
3605                            break terminate;
3606                        default:
3607                            nextTokenJSDoc();
3608                    }
3609                }
3610
3611                scanner.setInJSDocType(false);
3612                return finishNode(moduleTag, pos);
3613            }
3614
3615            const hasDotDotDot = parseOptional(SyntaxKind.DotDotDotToken);
3616            let type = parseTypeOrTypePredicate();
3617            scanner.setInJSDocType(false);
3618            if (hasDotDotDot) {
3619                type = finishNode(factory.createJSDocVariadicType(type), pos);
3620            }
3621            if (token() === SyntaxKind.EqualsToken) {
3622                nextToken();
3623                return finishNode(factory.createJSDocOptionalType(type), pos);
3624            }
3625            return type;
3626        }
3627
3628        function parseTypeQuery(): TypeQueryNode {
3629            const pos = getNodePos();
3630            parseExpected(SyntaxKind.TypeOfKeyword);
3631            const entityName = parseEntityName(/*allowReservedWords*/ true);
3632            // Make sure we perform ASI to prevent parsing the next line's type arguments as part of an instantiation expression.
3633            const typeArguments = !scanner.hasPrecedingLineBreak() ? tryParseTypeArguments() : undefined;
3634            return finishNode(factory.createTypeQueryNode(entityName, typeArguments), pos);
3635        }
3636
3637        function parseTypeParameter(position?: number): TypeParameterDeclaration {
3638            const pos = getNodePos();
3639            const modifiers = parseModifiers();
3640            const name = position !== undefined ? parseEtsIdentifier(position) : parseIdentifier();
3641            let constraint: TypeNode | undefined;
3642            let expression: Expression | undefined;
3643            if (parseOptional(SyntaxKind.ExtendsKeyword)) {
3644                // It's not uncommon for people to write improper constraints to a generic.  If the
3645                // user writes a constraint that is an expression and not an actual type, then parse
3646                // it out as an expression (so we can recover well), but report that a type is needed
3647                // instead.
3648                if (isStartOfType() || !isStartOfExpression()) {
3649                    constraint = parseType();
3650                }
3651                else {
3652                    // It was not a type, and it looked like an expression.  Parse out an expression
3653                    // here so we recover well.  Note: it is important that we call parseUnaryExpression
3654                    // and not parseExpression here.  If the user has:
3655                    //
3656                    //      <T extends "">
3657                    //
3658                    // We do *not* want to consume the `>` as we're consuming the expression for "".
3659                    expression = parseUnaryExpressionOrHigher();
3660                }
3661            }
3662
3663            const defaultType = parseOptional(SyntaxKind.EqualsToken) ? parseType() : undefined;
3664            const node = factory.createTypeParameterDeclaration(modifiers, name, constraint, defaultType);
3665            node.expression = expression;
3666            return position !== undefined ? finishVirtualNode(node, position, position) : finishNode(node, pos);
3667        }
3668
3669        function parseTypeParameters(): NodeArray<TypeParameterDeclaration> | undefined {
3670            if (token() === SyntaxKind.LessThanToken) {
3671                return parseBracketedList(ParsingContext.TypeParameters, parseTypeParameter, SyntaxKind.LessThanToken, SyntaxKind.GreaterThanToken);
3672            }
3673        }
3674
3675        function parseEtsTypeParameters(pos: number): NodeArray<TypeParameterDeclaration> | undefined {
3676            return createNodeArray([parseTypeParameter(pos)], getNodePos());
3677        }
3678
3679        function parseEtsTypeArguments(pos: number, name: string): NodeArray<TypeNode> | undefined {
3680            if ((contextFlags & NodeFlags.JavaScriptFile) !== 0) {
3681                // TypeArguments must not be parsed in JavaScript files to avoid ambiguity with binary operators.
3682                return undefined;
3683            }
3684
3685            return createNodeArray([parseEtsType(pos, name)], getNodePos());
3686        }
3687
3688        function isStartOfParameter(isJSDocParameter: boolean): boolean {
3689            return token() === SyntaxKind.DotDotDotToken ||
3690                isBindingIdentifierOrPrivateIdentifierOrPattern() ||
3691                isModifierKind(token()) ||
3692                token() === SyntaxKind.AtToken ||
3693                isStartOfType(/*inStartOfParameter*/ !isJSDocParameter);
3694        }
3695
3696        function parseNameOfParameter(modifiers: NodeArray<ModifierLike> | undefined) {
3697            // FormalParameter [Yield,Await]:
3698            //      BindingElement[?Yield,?Await]
3699            const name = parseIdentifierOrPattern(Diagnostics.Private_identifiers_cannot_be_used_as_parameters);
3700            if (getFullWidth(name) === 0 && !some(modifiers) && isModifierKind(token())) {
3701                // in cases like
3702                // 'use strict'
3703                // function foo(static)
3704                // isParameter('static') === true, because of isModifier('static')
3705                // however 'static' is not a legal identifier in a strict mode.
3706                // so result of this function will be ParameterDeclaration (flags = 0, name = missing, type = undefined, initializer = undefined)
3707                // and current token will not change => parsing of the enclosing parameter list will last till the end of time (or OOM)
3708                // to avoid this we'll advance cursor to the next token.
3709                nextToken();
3710            }
3711            return name;
3712        }
3713
3714        function isParameterNameStart() {
3715            // Be permissive about await and yield by calling isBindingIdentifier instead of isIdentifier; disallowing
3716            // them during a speculative parse leads to many more follow-on errors than allowing the function to parse then later
3717            // complaining about the use of the keywords.
3718            return isBindingIdentifier() || token() === SyntaxKind.OpenBracketToken || token() === SyntaxKind.OpenBraceToken;
3719        }
3720
3721        function parseParameter(inOuterAwaitContext: boolean): ParameterDeclaration {
3722            return parseParameterWorker(inOuterAwaitContext);
3723        }
3724
3725        function parseParameterForSpeculation(inOuterAwaitContext: boolean): ParameterDeclaration | undefined {
3726            return parseParameterWorker(inOuterAwaitContext, /*allowAmbiguity*/ false);
3727        }
3728
3729        function parseParameterWorker(inOuterAwaitContext: boolean): ParameterDeclaration;
3730        function parseParameterWorker(inOuterAwaitContext: boolean, allowAmbiguity: false): ParameterDeclaration | undefined;
3731        function parseParameterWorker(inOuterAwaitContext: boolean, allowAmbiguity = true): ParameterDeclaration | undefined {
3732            const pos = getNodePos();
3733            const hasJSDoc = hasPrecedingJSDocComment();
3734
3735            // FormalParameter [Yield,Await]:
3736            //      BindingElement[?Yield,?Await]
3737
3738            // Decorators are parsed in the outer [Await] context, the rest of the parameter is parsed in the function's [Await] context.
3739            const decorators = inOuterAwaitContext ? doInAwaitContext(parseDecorators) : doOutsideOfAwaitContext(parseDecorators);
3740
3741            if (token() === SyntaxKind.ThisKeyword) {
3742                const node = factory.createParameterDeclaration(
3743                    decorators,
3744                    /*dotDotDotToken*/ undefined,
3745                    createIdentifier(/*isIdentifier*/ true),
3746                    /*questionToken*/ undefined,
3747                    parseTypeAnnotation(),
3748                    /*initializer*/ undefined
3749                );
3750
3751                if (decorators) {
3752                    parseErrorAtRange(decorators[0], Diagnostics.Decorators_may_not_be_applied_to_this_parameters);
3753                }
3754
3755                return withJSDoc(finishNode(node, pos), hasJSDoc);
3756            }
3757
3758            const savedTopLevel = topLevel;
3759            topLevel = false;
3760
3761            const modifiers = combineDecoratorsAndModifiers(decorators, parseModifiers());
3762            const dotDotDotToken = parseOptionalToken(SyntaxKind.DotDotDotToken);
3763
3764            if (!allowAmbiguity && !isParameterNameStart()) {
3765                return undefined;
3766            }
3767
3768            const node = withJSDoc(
3769                finishNode(
3770                    factory.createParameterDeclaration(
3771                        modifiers,
3772                        dotDotDotToken,
3773                        parseNameOfParameter(modifiers),
3774                        parseOptionalToken(SyntaxKind.QuestionToken),
3775                        parseTypeAnnotation(),
3776                        parseInitializer()
3777                    ),
3778                    pos
3779                ),
3780                hasJSDoc
3781            );
3782            topLevel = savedTopLevel;
3783            return node;
3784        }
3785
3786        function parseReturnType(returnToken: SyntaxKind.EqualsGreaterThanToken, isType: boolean): TypeNode;
3787        function parseReturnType(returnToken: SyntaxKind.ColonToken | SyntaxKind.EqualsGreaterThanToken, isType: boolean): TypeNode | undefined;
3788        function parseReturnType(returnToken: SyntaxKind.ColonToken | SyntaxKind.EqualsGreaterThanToken, isType: boolean) {
3789            if (shouldParseReturnType(returnToken, isType)) {
3790                return allowConditionalTypesAnd(parseTypeOrTypePredicate);
3791            }
3792        }
3793
3794        function shouldParseReturnType(returnToken: SyntaxKind.ColonToken | SyntaxKind.EqualsGreaterThanToken, isType: boolean): boolean {
3795            if (returnToken === SyntaxKind.EqualsGreaterThanToken) {
3796                parseExpected(returnToken);
3797                return true;
3798            }
3799            else if (parseOptional(SyntaxKind.ColonToken)) {
3800                return true;
3801            }
3802            else if (isType && token() === SyntaxKind.EqualsGreaterThanToken) {
3803                // This is easy to get backward, especially in type contexts, so parse the type anyway
3804                parseErrorAtCurrentToken(Diagnostics._0_expected, tokenToString(SyntaxKind.ColonToken));
3805                nextToken();
3806                return true;
3807            }
3808            return false;
3809        }
3810
3811        function parseParametersWorker(flags: SignatureFlags, allowAmbiguity: true): NodeArray<ParameterDeclaration>;
3812        function parseParametersWorker(flags: SignatureFlags, allowAmbiguity: false): NodeArray<ParameterDeclaration> | undefined;
3813        function parseParametersWorker(flags: SignatureFlags, allowAmbiguity: boolean): NodeArray<ParameterDeclaration> | undefined {
3814            // FormalParameters [Yield,Await]: (modified)
3815            //      [empty]
3816            //      FormalParameterList[?Yield,Await]
3817            //
3818            // FormalParameter[Yield,Await]: (modified)
3819            //      BindingElement[?Yield,Await]
3820            //
3821            // BindingElement [Yield,Await]: (modified)
3822            //      SingleNameBinding[?Yield,?Await]
3823            //      BindingPattern[?Yield,?Await]Initializer [In, ?Yield,?Await] opt
3824            //
3825            // SingleNameBinding [Yield,Await]:
3826            //      BindingIdentifier[?Yield,?Await]Initializer [In, ?Yield,?Await] opt
3827            const savedYieldContext = inYieldContext();
3828            const savedAwaitContext = inAwaitContext();
3829
3830            setYieldContext(!!(flags & SignatureFlags.Yield));
3831            setAwaitContext(!!(flags & SignatureFlags.Await));
3832
3833            const parameters = flags & SignatureFlags.JSDoc ?
3834                parseDelimitedList(ParsingContext.JSDocParameters, parseJSDocParameter) :
3835                parseDelimitedList(ParsingContext.Parameters, () => allowAmbiguity ? parseParameter(savedAwaitContext) : parseParameterForSpeculation(savedAwaitContext));
3836
3837            setYieldContext(savedYieldContext);
3838            setAwaitContext(savedAwaitContext);
3839
3840            return parameters;
3841        }
3842
3843        function parseParameters(flags: SignatureFlags): NodeArray<ParameterDeclaration> {
3844            // FormalParameters [Yield,Await]: (modified)
3845            //      [empty]
3846            //      FormalParameterList[?Yield,Await]
3847            //
3848            // FormalParameter[Yield,Await]: (modified)
3849            //      BindingElement[?Yield,Await]
3850            //
3851            // BindingElement [Yield,Await]: (modified)
3852            //      SingleNameBinding[?Yield,?Await]
3853            //      BindingPattern[?Yield,?Await]Initializer [In, ?Yield,?Await] opt
3854            //
3855            // SingleNameBinding [Yield,Await]:
3856            //      BindingIdentifier[?Yield,?Await]Initializer [In, ?Yield,?Await] opt
3857            if (!parseExpected(SyntaxKind.OpenParenToken)) {
3858                return createMissingList<ParameterDeclaration>();
3859            }
3860
3861            const parameters = parseParametersWorker(flags, /*allowAmbiguity*/ true);
3862            parseExpected(SyntaxKind.CloseParenToken);
3863            return parameters;
3864        }
3865
3866        function parseTypeMemberSemicolon() {
3867            // We allow type members to be separated by commas or (possibly ASI) semicolons.
3868            // First check if it was a comma.  If so, we're done with the member.
3869            if (parseOptional(SyntaxKind.CommaToken)) {
3870                return;
3871            }
3872
3873            // Didn't have a comma.  We must have a (possible ASI) semicolon.
3874            parseSemicolon();
3875        }
3876
3877        function parseSignatureMember(kind: SyntaxKind.CallSignature | SyntaxKind.ConstructSignature): CallSignatureDeclaration | ConstructSignatureDeclaration {
3878            const pos = getNodePos();
3879            const hasJSDoc = hasPrecedingJSDocComment();
3880            if (kind === SyntaxKind.ConstructSignature) {
3881                parseExpected(SyntaxKind.NewKeyword);
3882            }
3883
3884            const typeParameters = parseTypeParameters();
3885            const parameters = parseParameters(SignatureFlags.Type);
3886            const type = parseReturnType(SyntaxKind.ColonToken, /*isType*/ true);
3887            parseTypeMemberSemicolon();
3888            const node = kind === SyntaxKind.CallSignature
3889                ? factory.createCallSignature(typeParameters, parameters, type)
3890                : factory.createConstructSignature(typeParameters, parameters, type);
3891            return withJSDoc(finishNode(node, pos), hasJSDoc);
3892        }
3893
3894        function isIndexSignature(): boolean {
3895            return token() === SyntaxKind.OpenBracketToken && lookAhead(isUnambiguouslyIndexSignature);
3896        }
3897
3898        function isUnambiguouslyIndexSignature() {
3899            // The only allowed sequence is:
3900            //
3901            //   [id:
3902            //
3903            // However, for error recovery, we also check the following cases:
3904            //
3905            //   [...
3906            //   [id,
3907            //   [id?,
3908            //   [id?:
3909            //   [id?]
3910            //   [public id
3911            //   [private id
3912            //   [protected id
3913            //   []
3914            //
3915            nextToken();
3916            if (token() === SyntaxKind.DotDotDotToken || token() === SyntaxKind.CloseBracketToken) {
3917                return true;
3918            }
3919
3920            if (isModifierKind(token())) {
3921                nextToken();
3922                if (isIdentifier()) {
3923                    return true;
3924                }
3925            }
3926            else if (!isIdentifier()) {
3927                return false;
3928            }
3929            else {
3930                // Skip the identifier
3931                nextToken();
3932            }
3933
3934            // A colon signifies a well formed indexer
3935            // A comma should be a badly formed indexer because comma expressions are not allowed
3936            // in computed properties.
3937            if (token() === SyntaxKind.ColonToken || token() === SyntaxKind.CommaToken) {
3938                return true;
3939            }
3940
3941            // Question mark could be an indexer with an optional property,
3942            // or it could be a conditional expression in a computed property.
3943            if (token() !== SyntaxKind.QuestionToken) {
3944                return false;
3945            }
3946
3947            // If any of the following tokens are after the question mark, it cannot
3948            // be a conditional expression, so treat it as an indexer.
3949            nextToken();
3950            return token() === SyntaxKind.ColonToken || token() === SyntaxKind.CommaToken || token() === SyntaxKind.CloseBracketToken;
3951        }
3952
3953        function parseIndexSignatureDeclaration(pos: number, hasJSDoc: boolean, decorators: NodeArray<Decorator> | undefined, modifiers: NodeArray<Modifier> | undefined): IndexSignatureDeclaration {
3954            const parameters = parseBracketedList<ParameterDeclaration>(ParsingContext.Parameters, () => parseParameter(/*inOuterAwaitContext*/ false), SyntaxKind.OpenBracketToken, SyntaxKind.CloseBracketToken);
3955            const type = parseTypeAnnotation();
3956            parseTypeMemberSemicolon();
3957            const node = factory.createIndexSignature(modifiers, parameters, type);
3958            (node as Mutable<IndexSignatureDeclaration>).illegalDecorators = decorators;
3959            return withJSDoc(finishNode(node, pos), hasJSDoc);
3960        }
3961
3962        function parsePropertyOrMethodSignature(pos: number, hasJSDoc: boolean, modifiers: NodeArray<Modifier> | undefined): PropertySignature | MethodSignature {
3963            const name = parsePropertyName();
3964            const questionToken = parseOptionalToken(SyntaxKind.QuestionToken);
3965            let node: PropertySignature | MethodSignature;
3966            if (token() === SyntaxKind.OpenParenToken || token() === SyntaxKind.LessThanToken) {
3967                // Method signatures don't exist in expression contexts.  So they have neither
3968                // [Yield] nor [Await]
3969                const typeParameters = parseTypeParameters();
3970                const parameters = parseParameters(SignatureFlags.Type);
3971                const type = parseReturnType(SyntaxKind.ColonToken, /*isType*/ true);
3972                node = factory.createMethodSignature(modifiers, name, questionToken, typeParameters, parameters, type);
3973            }
3974            else {
3975                const type = parseTypeAnnotation();
3976                node = factory.createPropertySignature(modifiers, name, questionToken, type);
3977                // Although type literal properties cannot not have initializers, we attempt
3978                // to parse an initializer so we can report in the checker that an interface
3979                // property or type literal property cannot have an initializer.
3980                if (token() === SyntaxKind.EqualsToken) (node as Mutable<PropertySignature>).initializer = parseInitializer();
3981            }
3982            parseTypeMemberSemicolon();
3983            return withJSDoc(finishNode(node, pos), hasJSDoc);
3984        }
3985
3986        function isTypeMemberStart(): boolean {
3987            // Return true if we have the start of a signature member
3988            if (token() === SyntaxKind.OpenParenToken ||
3989                token() === SyntaxKind.LessThanToken ||
3990                token() === SyntaxKind.GetKeyword ||
3991                token() === SyntaxKind.SetKeyword) {
3992                return true;
3993            }
3994            let idToken = false;
3995            // Eat up all modifiers, but hold on to the last one in case it is actually an identifier
3996            while (isModifierKind(token())) {
3997                idToken = true;
3998                nextToken();
3999            }
4000            // Index signatures and computed property names are type members
4001            if (token() === SyntaxKind.OpenBracketToken) {
4002                return true;
4003            }
4004            // Try to get the first property-like token following all modifiers
4005            if (isLiteralPropertyName()) {
4006                idToken = true;
4007                nextToken();
4008            }
4009            // If we were able to get any potential identifier, check that it is
4010            // the start of a member declaration
4011            if (idToken) {
4012                return token() === SyntaxKind.OpenParenToken ||
4013                    token() === SyntaxKind.LessThanToken ||
4014                    token() === SyntaxKind.QuestionToken ||
4015                    token() === SyntaxKind.ColonToken ||
4016                    token() === SyntaxKind.CommaToken ||
4017                    canParseSemicolon();
4018            }
4019            return false;
4020        }
4021
4022        function parseTypeMember(): TypeElement {
4023            if (token() === SyntaxKind.OpenParenToken || token() === SyntaxKind.LessThanToken) {
4024                return parseSignatureMember(SyntaxKind.CallSignature);
4025            }
4026            if (token() === SyntaxKind.NewKeyword && lookAhead(nextTokenIsOpenParenOrLessThan)) {
4027                return parseSignatureMember(SyntaxKind.ConstructSignature);
4028            }
4029            const pos = getNodePos();
4030            const hasJSDoc = hasPrecedingJSDocComment();
4031            const modifiers = parseModifiers();
4032            if (parseContextualModifier(SyntaxKind.GetKeyword)) {
4033                return parseAccessorDeclaration(pos, hasJSDoc, /*decorators*/ undefined, modifiers, SyntaxKind.GetAccessor, SignatureFlags.Type);
4034            }
4035
4036            if (parseContextualModifier(SyntaxKind.SetKeyword)) {
4037                return parseAccessorDeclaration(pos, hasJSDoc, /*decorators*/ undefined, modifiers, SyntaxKind.SetAccessor, SignatureFlags.Type);
4038            }
4039
4040            if (isIndexSignature()) {
4041                return parseIndexSignatureDeclaration(pos, hasJSDoc, /*decorators*/ undefined, modifiers);
4042            }
4043            return parsePropertyOrMethodSignature(pos, hasJSDoc, modifiers);
4044        }
4045
4046        function nextTokenIsOpenParenOrLessThan() {
4047            nextToken();
4048            return token() === SyntaxKind.OpenParenToken || token() === SyntaxKind.LessThanToken;
4049        }
4050
4051        function nextTokenIsDot() {
4052            return nextToken() === SyntaxKind.DotToken;
4053        }
4054
4055        function nextTokenIsOpenParenOrLessThanOrDot() {
4056            switch (nextToken()) {
4057                case SyntaxKind.OpenParenToken:
4058                case SyntaxKind.LessThanToken:
4059                case SyntaxKind.DotToken:
4060                    return true;
4061            }
4062            return false;
4063        }
4064
4065        function parseTypeLiteral(): TypeLiteralNode {
4066            const pos = getNodePos();
4067            return finishNode(factory.createTypeLiteralNode(parseObjectTypeMembers()), pos);
4068        }
4069
4070        function parseObjectTypeMembers(): NodeArray<TypeElement> {
4071            let members: NodeArray<TypeElement>;
4072            if (parseExpected(SyntaxKind.OpenBraceToken)) {
4073                members = parseList(ParsingContext.TypeMembers, parseTypeMember);
4074                parseExpected(SyntaxKind.CloseBraceToken);
4075            }
4076            else {
4077                members = createMissingList<TypeElement>();
4078            }
4079
4080            return members;
4081        }
4082
4083        function isStartOfMappedType() {
4084            nextToken();
4085            if (token() === SyntaxKind.PlusToken || token() === SyntaxKind.MinusToken) {
4086                return nextToken() === SyntaxKind.ReadonlyKeyword;
4087            }
4088            if (token() === SyntaxKind.ReadonlyKeyword) {
4089                nextToken();
4090            }
4091            return token() === SyntaxKind.OpenBracketToken && nextTokenIsIdentifier() && nextToken() === SyntaxKind.InKeyword;
4092        }
4093
4094        function parseMappedTypeParameter() {
4095            const pos = getNodePos();
4096            const name = parseIdentifierName();
4097            parseExpected(SyntaxKind.InKeyword);
4098            const type = parseType();
4099            return finishNode(factory.createTypeParameterDeclaration(/*modifiers*/ undefined, name, type, /*defaultType*/ undefined), pos);
4100        }
4101
4102        function parseMappedType() {
4103            const pos = getNodePos();
4104            parseExpected(SyntaxKind.OpenBraceToken);
4105            let readonlyToken: ReadonlyKeyword | PlusToken | MinusToken | undefined;
4106            if (token() === SyntaxKind.ReadonlyKeyword || token() === SyntaxKind.PlusToken || token() === SyntaxKind.MinusToken) {
4107                readonlyToken = parseTokenNode<ReadonlyKeyword | PlusToken | MinusToken>();
4108                if (readonlyToken.kind !== SyntaxKind.ReadonlyKeyword) {
4109                    parseExpected(SyntaxKind.ReadonlyKeyword);
4110                }
4111            }
4112            parseExpected(SyntaxKind.OpenBracketToken);
4113            const typeParameter = parseMappedTypeParameter();
4114            const nameType = parseOptional(SyntaxKind.AsKeyword) ? parseType() : undefined;
4115            parseExpected(SyntaxKind.CloseBracketToken);
4116            let questionToken: QuestionToken | PlusToken | MinusToken | undefined;
4117            if (token() === SyntaxKind.QuestionToken || token() === SyntaxKind.PlusToken || token() === SyntaxKind.MinusToken) {
4118                questionToken = parseTokenNode<QuestionToken | PlusToken | MinusToken>();
4119                if (questionToken.kind !== SyntaxKind.QuestionToken) {
4120                    parseExpected(SyntaxKind.QuestionToken);
4121                }
4122            }
4123            const type = parseTypeAnnotation();
4124            parseSemicolon();
4125            const members = parseList(ParsingContext.TypeMembers, parseTypeMember);
4126            parseExpected(SyntaxKind.CloseBraceToken);
4127            return finishNode(factory.createMappedTypeNode(readonlyToken, typeParameter, nameType, questionToken, type, members), pos);
4128        }
4129
4130        function parseTupleElementType() {
4131            const pos = getNodePos();
4132            if (parseOptional(SyntaxKind.DotDotDotToken)) {
4133                return finishNode(factory.createRestTypeNode(parseType()), pos);
4134            }
4135            const type = parseType();
4136            if (isJSDocNullableType(type) && type.pos === type.type.pos) {
4137                const node = factory.createOptionalTypeNode(type.type);
4138                setTextRange(node, type);
4139                (node as Mutable<Node>).flags = type.flags;
4140                return node;
4141            }
4142            return type;
4143        }
4144
4145        function isNextTokenColonOrQuestionColon() {
4146            return nextToken() === SyntaxKind.ColonToken || (token() === SyntaxKind.QuestionToken && nextToken() === SyntaxKind.ColonToken);
4147        }
4148
4149        function isTupleElementName() {
4150            if (token() === SyntaxKind.DotDotDotToken) {
4151                return tokenIsIdentifierOrKeyword(nextToken()) && isNextTokenColonOrQuestionColon();
4152            }
4153            return tokenIsIdentifierOrKeyword(token()) && isNextTokenColonOrQuestionColon();
4154        }
4155
4156        function parseTupleElementNameOrTupleElementType() {
4157            if (lookAhead(isTupleElementName)) {
4158                const pos = getNodePos();
4159                const hasJSDoc = hasPrecedingJSDocComment();
4160                const dotDotDotToken = parseOptionalToken(SyntaxKind.DotDotDotToken);
4161                const name = parseIdentifierName();
4162                const questionToken = parseOptionalToken(SyntaxKind.QuestionToken);
4163                parseExpected(SyntaxKind.ColonToken);
4164                const type = parseTupleElementType();
4165                const node = factory.createNamedTupleMember(dotDotDotToken, name, questionToken, type);
4166                return withJSDoc(finishNode(node, pos), hasJSDoc);
4167            }
4168            return parseTupleElementType();
4169        }
4170
4171        function parseTupleType(): TupleTypeNode {
4172            const pos = getNodePos();
4173            return finishNode(
4174                factory.createTupleTypeNode(
4175                    parseBracketedList(ParsingContext.TupleElementTypes, parseTupleElementNameOrTupleElementType, SyntaxKind.OpenBracketToken, SyntaxKind.CloseBracketToken)
4176                ),
4177                pos
4178            );
4179        }
4180
4181        function parseParenthesizedType(): TypeNode {
4182            const pos = getNodePos();
4183            parseExpected(SyntaxKind.OpenParenToken);
4184            const type = parseType();
4185            parseExpected(SyntaxKind.CloseParenToken);
4186            return finishNode(factory.createParenthesizedType(type), pos);
4187        }
4188
4189        function parseModifiersForConstructorType(): NodeArray<Modifier> | undefined {
4190            let modifiers: NodeArray<Modifier> | undefined;
4191            if (token() === SyntaxKind.AbstractKeyword) {
4192                const pos = getNodePos();
4193                nextToken();
4194                const modifier = finishNode(factory.createToken(SyntaxKind.AbstractKeyword), pos);
4195                modifiers = createNodeArray<Modifier>([modifier], pos);
4196            }
4197            return modifiers;
4198        }
4199
4200        function parseFunctionOrConstructorType(): TypeNode {
4201            const pos = getNodePos();
4202            const hasJSDoc = hasPrecedingJSDocComment();
4203            const modifiers = parseModifiersForConstructorType();
4204            const isConstructorType = parseOptional(SyntaxKind.NewKeyword);
4205            const typeParameters = parseTypeParameters();
4206            const parameters = parseParameters(SignatureFlags.Type);
4207            const type = parseReturnType(SyntaxKind.EqualsGreaterThanToken, /*isType*/ false);
4208            const node = isConstructorType
4209                ? factory.createConstructorTypeNode(modifiers, typeParameters, parameters, type)
4210                : factory.createFunctionTypeNode(typeParameters, parameters, type);
4211            if (!isConstructorType) (node as Mutable<FunctionTypeNode>).modifiers = modifiers;
4212            return withJSDoc(finishNode(node, pos), hasJSDoc);
4213        }
4214
4215        function parseKeywordAndNoDot(): TypeNode | undefined {
4216            const node = parseTokenNode<TypeNode>();
4217            return token() === SyntaxKind.DotToken ? undefined : node;
4218        }
4219
4220        function parseLiteralTypeNode(negative?: boolean): LiteralTypeNode {
4221            const pos = getNodePos();
4222            if (negative) {
4223                nextToken();
4224            }
4225            let expression: BooleanLiteral | NullLiteral | LiteralExpression | PrefixUnaryExpression =
4226                token() === SyntaxKind.TrueKeyword || token() === SyntaxKind.FalseKeyword || token() === SyntaxKind.NullKeyword ?
4227                    parseTokenNode<BooleanLiteral | NullLiteral>() :
4228                    parseLiteralLikeNode(token()) as LiteralExpression;
4229            if (negative) {
4230                expression = finishNode(factory.createPrefixUnaryExpression(SyntaxKind.MinusToken, expression), pos);
4231            }
4232            return finishNode(factory.createLiteralTypeNode(expression), pos);
4233        }
4234
4235        function isStartOfTypeOfImportType() {
4236            nextToken();
4237            return token() === SyntaxKind.ImportKeyword;
4238        }
4239
4240        function parseImportTypeAssertions(): ImportTypeAssertionContainer {
4241            const pos = getNodePos();
4242            const openBracePosition = scanner.getTokenPos();
4243            parseExpected(SyntaxKind.OpenBraceToken);
4244            const multiLine = scanner.hasPrecedingLineBreak();
4245            parseExpected(SyntaxKind.AssertKeyword);
4246            parseExpected(SyntaxKind.ColonToken);
4247            const clause = parseAssertClause(/*skipAssertKeyword*/ true);
4248            if (!parseExpected(SyntaxKind.CloseBraceToken)) {
4249                const lastError = lastOrUndefined(parseDiagnostics);
4250                if (lastError && lastError.code === Diagnostics._0_expected.code) {
4251                    addRelatedInfo(
4252                        lastError,
4253                        createDetachedDiagnostic(fileName, openBracePosition, 1, Diagnostics.The_parser_expected_to_find_a_1_to_match_the_0_token_here, "{", "}")
4254                    );
4255                }
4256            }
4257            return finishNode(factory.createImportTypeAssertionContainer(clause, multiLine), pos);
4258        }
4259
4260        function parseImportType(): ImportTypeNode {
4261            sourceFlags |= NodeFlags.PossiblyContainsDynamicImport;
4262            const pos = getNodePos();
4263            const isTypeOf = parseOptional(SyntaxKind.TypeOfKeyword);
4264            parseExpected(SyntaxKind.ImportKeyword);
4265            parseExpected(SyntaxKind.OpenParenToken);
4266            const type = parseType();
4267            let assertions: ImportTypeAssertionContainer | undefined;
4268            if (parseOptional(SyntaxKind.CommaToken)) {
4269                assertions = parseImportTypeAssertions();
4270            }
4271            parseExpected(SyntaxKind.CloseParenToken);
4272            const qualifier = parseOptional(SyntaxKind.DotToken) ? parseEntityNameOfTypeReference() : undefined;
4273            const typeArguments = parseTypeArgumentsOfTypeReference();
4274            return finishNode(factory.createImportTypeNode(type, assertions, qualifier, typeArguments, isTypeOf), pos);
4275        }
4276
4277        function nextTokenIsNumericOrBigIntLiteral() {
4278            nextToken();
4279            return token() === SyntaxKind.NumericLiteral || token() === SyntaxKind.BigIntLiteral;
4280        }
4281
4282        function parseNonArrayType(): TypeNode {
4283            switch (token()) {
4284                case SyntaxKind.AnyKeyword:
4285                case SyntaxKind.UnknownKeyword:
4286                case SyntaxKind.StringKeyword:
4287                case SyntaxKind.NumberKeyword:
4288                case SyntaxKind.BigIntKeyword:
4289                case SyntaxKind.SymbolKeyword:
4290                case SyntaxKind.BooleanKeyword:
4291                case SyntaxKind.UndefinedKeyword:
4292                case SyntaxKind.NeverKeyword:
4293                case SyntaxKind.ObjectKeyword:
4294                    // If these are followed by a dot, then parse these out as a dotted type reference instead.
4295                    return tryParse(parseKeywordAndNoDot) || parseTypeReference();
4296                case SyntaxKind.AsteriskEqualsToken:
4297                    // If there is '*=', treat it as * followed by postfix =
4298                    scanner.reScanAsteriskEqualsToken();
4299                    // falls through
4300                case SyntaxKind.AsteriskToken:
4301                    return parseJSDocAllType();
4302                case SyntaxKind.QuestionQuestionToken:
4303                    // If there is '??', treat it as prefix-'?' in JSDoc type.
4304                    scanner.reScanQuestionToken();
4305                    // falls through
4306                case SyntaxKind.QuestionToken:
4307                    return parseJSDocUnknownOrNullableType();
4308                case SyntaxKind.FunctionKeyword:
4309                    return parseJSDocFunctionType();
4310                case SyntaxKind.ExclamationToken:
4311                    return parseJSDocNonNullableType();
4312                case SyntaxKind.NoSubstitutionTemplateLiteral:
4313                case SyntaxKind.StringLiteral:
4314                case SyntaxKind.NumericLiteral:
4315                case SyntaxKind.BigIntLiteral:
4316                case SyntaxKind.TrueKeyword:
4317                case SyntaxKind.FalseKeyword:
4318                case SyntaxKind.NullKeyword:
4319                    return parseLiteralTypeNode();
4320                case SyntaxKind.MinusToken:
4321                    return lookAhead(nextTokenIsNumericOrBigIntLiteral) ? parseLiteralTypeNode(/*negative*/ true) : parseTypeReference();
4322                case SyntaxKind.VoidKeyword:
4323                    return parseTokenNode<TypeNode>();
4324                case SyntaxKind.ThisKeyword: {
4325                    const thisKeyword = parseThisTypeNode();
4326                    if (token() === SyntaxKind.IsKeyword && !scanner.hasPrecedingLineBreak()) {
4327                        return parseThisTypePredicate(thisKeyword);
4328                    }
4329                    else {
4330                        return thisKeyword;
4331                    }
4332                }
4333                case SyntaxKind.TypeOfKeyword:
4334                    return lookAhead(isStartOfTypeOfImportType) ? parseImportType() : parseTypeQuery();
4335                case SyntaxKind.OpenBraceToken:
4336                    return lookAhead(isStartOfMappedType) ? parseMappedType() : parseTypeLiteral();
4337                case SyntaxKind.OpenBracketToken:
4338                    return parseTupleType();
4339                case SyntaxKind.OpenParenToken:
4340                    return parseParenthesizedType();
4341                case SyntaxKind.ImportKeyword:
4342                    return parseImportType();
4343                case SyntaxKind.AssertsKeyword:
4344                    return lookAhead(nextTokenIsIdentifierOrKeywordOnSameLine) ? parseAssertsTypePredicate() : parseTypeReference();
4345                case SyntaxKind.TemplateHead:
4346                    return parseTemplateType();
4347                default:
4348                    return parseTypeReference();
4349            }
4350        }
4351
4352        function isStartOfType(inStartOfParameter?: boolean): boolean {
4353            switch (token()) {
4354                case SyntaxKind.AnyKeyword:
4355                case SyntaxKind.UnknownKeyword:
4356                case SyntaxKind.StringKeyword:
4357                case SyntaxKind.NumberKeyword:
4358                case SyntaxKind.BigIntKeyword:
4359                case SyntaxKind.BooleanKeyword:
4360                case SyntaxKind.ReadonlyKeyword:
4361                case SyntaxKind.SymbolKeyword:
4362                case SyntaxKind.UniqueKeyword:
4363                case SyntaxKind.VoidKeyword:
4364                case SyntaxKind.UndefinedKeyword:
4365                case SyntaxKind.NullKeyword:
4366                case SyntaxKind.ThisKeyword:
4367                case SyntaxKind.TypeOfKeyword:
4368                case SyntaxKind.NeverKeyword:
4369                case SyntaxKind.OpenBraceToken:
4370                case SyntaxKind.OpenBracketToken:
4371                case SyntaxKind.LessThanToken:
4372                case SyntaxKind.BarToken:
4373                case SyntaxKind.AmpersandToken:
4374                case SyntaxKind.NewKeyword:
4375                case SyntaxKind.StringLiteral:
4376                case SyntaxKind.NumericLiteral:
4377                case SyntaxKind.BigIntLiteral:
4378                case SyntaxKind.TrueKeyword:
4379                case SyntaxKind.FalseKeyword:
4380                case SyntaxKind.ObjectKeyword:
4381                case SyntaxKind.AsteriskToken:
4382                case SyntaxKind.QuestionToken:
4383                case SyntaxKind.ExclamationToken:
4384                case SyntaxKind.DotDotDotToken:
4385                case SyntaxKind.InferKeyword:
4386                case SyntaxKind.ImportKeyword:
4387                case SyntaxKind.AssertsKeyword:
4388                case SyntaxKind.NoSubstitutionTemplateLiteral:
4389                case SyntaxKind.TemplateHead:
4390                    return true;
4391                case SyntaxKind.FunctionKeyword:
4392                    return !inStartOfParameter;
4393                case SyntaxKind.MinusToken:
4394                    return !inStartOfParameter && lookAhead(nextTokenIsNumericOrBigIntLiteral);
4395                case SyntaxKind.OpenParenToken:
4396                    // Only consider '(' the start of a type if followed by ')', '...', an identifier, a modifier,
4397                    // or something that starts a type. We don't want to consider things like '(1)' a type.
4398                    return !inStartOfParameter && lookAhead(isStartOfParenthesizedOrFunctionType);
4399                default:
4400                    return isIdentifier();
4401            }
4402        }
4403
4404        function isStartOfParenthesizedOrFunctionType() {
4405            nextToken();
4406            return token() === SyntaxKind.CloseParenToken || isStartOfParameter(/*isJSDocParameter*/ false) || isStartOfType();
4407        }
4408
4409        function parsePostfixTypeOrHigher(): TypeNode {
4410            const pos = getNodePos();
4411            let type = parseNonArrayType();
4412            while (!scanner.hasPrecedingLineBreak()) {
4413                switch (token()) {
4414                    case SyntaxKind.ExclamationToken:
4415                        nextToken();
4416                        type = finishNode(factory.createJSDocNonNullableType(type, /*postfix*/ true), pos);
4417                        break;
4418                    case SyntaxKind.QuestionToken:
4419                        // If next token is start of a type we have a conditional type
4420                        if (lookAhead(nextTokenIsStartOfType)) {
4421                            return type;
4422                        }
4423                        nextToken();
4424                        type = finishNode(factory.createJSDocNullableType(type, /*postfix*/ true), pos);
4425                        break;
4426                    case SyntaxKind.OpenBracketToken:
4427                        parseExpected(SyntaxKind.OpenBracketToken);
4428                        if (isStartOfType()) {
4429                            const indexType = parseType();
4430                            parseExpected(SyntaxKind.CloseBracketToken);
4431                            type = finishNode(factory.createIndexedAccessTypeNode(type, indexType), pos);
4432                        }
4433                        else {
4434                            parseExpected(SyntaxKind.CloseBracketToken);
4435                            type = finishNode(factory.createArrayTypeNode(type), pos);
4436                        }
4437                        break;
4438                    default:
4439                        return type;
4440                }
4441            }
4442            return type;
4443        }
4444
4445        function parseTypeOperator(operator: SyntaxKind.KeyOfKeyword | SyntaxKind.UniqueKeyword | SyntaxKind.ReadonlyKeyword) {
4446            const pos = getNodePos();
4447            parseExpected(operator);
4448            return finishNode(factory.createTypeOperatorNode(operator, parseTypeOperatorOrHigher()), pos);
4449        }
4450
4451        function tryParseConstraintOfInferType() {
4452            if (parseOptional(SyntaxKind.ExtendsKeyword)) {
4453                const constraint = disallowConditionalTypesAnd(parseType);
4454                if (inDisallowConditionalTypesContext() || token() !== SyntaxKind.QuestionToken) {
4455                    return constraint;
4456                }
4457            }
4458        }
4459
4460        function parseTypeParameterOfInferType(): TypeParameterDeclaration {
4461            const pos = getNodePos();
4462            const name = parseIdentifier();
4463            const constraint = tryParse(tryParseConstraintOfInferType);
4464            const node = factory.createTypeParameterDeclaration(/*modifiers*/ undefined, name, constraint);
4465            return finishNode(node, pos);
4466        }
4467
4468        function parseInferType(): InferTypeNode {
4469            const pos = getNodePos();
4470            parseExpected(SyntaxKind.InferKeyword);
4471            return finishNode(factory.createInferTypeNode(parseTypeParameterOfInferType()), pos);
4472        }
4473
4474        function parseTypeOperatorOrHigher(): TypeNode {
4475            const operator = token();
4476            switch (operator) {
4477                case SyntaxKind.KeyOfKeyword:
4478                case SyntaxKind.UniqueKeyword:
4479                case SyntaxKind.ReadonlyKeyword:
4480                    return parseTypeOperator(operator);
4481                case SyntaxKind.InferKeyword:
4482                    return parseInferType();
4483            }
4484            return allowConditionalTypesAnd(parsePostfixTypeOrHigher);
4485        }
4486
4487        function parseFunctionOrConstructorTypeToError(
4488            isInUnionType: boolean
4489        ): TypeNode | undefined {
4490            // the function type and constructor type shorthand notation
4491            // are not allowed directly in unions and intersections, but we'll
4492            // try to parse them gracefully and issue a helpful message.
4493            if (isStartOfFunctionTypeOrConstructorType()) {
4494                const type = parseFunctionOrConstructorType();
4495                let diagnostic: DiagnosticMessage;
4496                if (isFunctionTypeNode(type)) {
4497                    diagnostic = isInUnionType
4498                        ? Diagnostics.Function_type_notation_must_be_parenthesized_when_used_in_a_union_type
4499                        : Diagnostics.Function_type_notation_must_be_parenthesized_when_used_in_an_intersection_type;
4500                }
4501                else {
4502                    diagnostic = isInUnionType
4503                        ? Diagnostics.Constructor_type_notation_must_be_parenthesized_when_used_in_a_union_type
4504                        : Diagnostics.Constructor_type_notation_must_be_parenthesized_when_used_in_an_intersection_type;
4505
4506                }
4507                parseErrorAtRange(type, diagnostic);
4508                return type;
4509            }
4510            return undefined;
4511        }
4512
4513        function parseUnionOrIntersectionType(
4514            operator: SyntaxKind.BarToken | SyntaxKind.AmpersandToken,
4515            parseConstituentType: () => TypeNode,
4516            createTypeNode: (types: NodeArray<TypeNode>) => UnionOrIntersectionTypeNode
4517        ): TypeNode {
4518            const pos = getNodePos();
4519            const isUnionType = operator === SyntaxKind.BarToken;
4520            const hasLeadingOperator = parseOptional(operator);
4521            let type = hasLeadingOperator && parseFunctionOrConstructorTypeToError(isUnionType)
4522                || parseConstituentType();
4523            if (token() === operator || hasLeadingOperator) {
4524                const types = [type];
4525                while (parseOptional(operator)) {
4526                    types.push(parseFunctionOrConstructorTypeToError(isUnionType) || parseConstituentType());
4527                }
4528                type = finishNode(createTypeNode(createNodeArray(types, pos)), pos);
4529            }
4530            return type;
4531        }
4532
4533        function parseIntersectionTypeOrHigher(): TypeNode {
4534            return parseUnionOrIntersectionType(SyntaxKind.AmpersandToken, parseTypeOperatorOrHigher, factory.createIntersectionTypeNode);
4535        }
4536
4537        function parseUnionTypeOrHigher(): TypeNode {
4538            return parseUnionOrIntersectionType(SyntaxKind.BarToken, parseIntersectionTypeOrHigher, factory.createUnionTypeNode);
4539        }
4540
4541        function nextTokenIsNewKeyword(): boolean {
4542            nextToken();
4543            return token() === SyntaxKind.NewKeyword;
4544        }
4545
4546        function isStartOfFunctionTypeOrConstructorType(): boolean {
4547            if (token() === SyntaxKind.LessThanToken) {
4548                return true;
4549            }
4550            if (token() === SyntaxKind.OpenParenToken && lookAhead(isUnambiguouslyStartOfFunctionType)) {
4551                return true;
4552            }
4553            return token() === SyntaxKind.NewKeyword ||
4554                token() === SyntaxKind.AbstractKeyword && lookAhead(nextTokenIsNewKeyword);
4555        }
4556
4557        function skipParameterStart(): boolean {
4558            if (isModifierKind(token())) {
4559                // Skip modifiers
4560                parseModifiers();
4561            }
4562            if (isIdentifier() || token() === SyntaxKind.ThisKeyword) {
4563                nextToken();
4564                return true;
4565            }
4566            if (token() === SyntaxKind.OpenBracketToken || token() === SyntaxKind.OpenBraceToken) {
4567                // Return true if we can parse an array or object binding pattern with no errors
4568                const previousErrorCount = parseDiagnostics.length;
4569                parseIdentifierOrPattern();
4570                return previousErrorCount === parseDiagnostics.length;
4571            }
4572            return false;
4573        }
4574
4575        function isUnambiguouslyStartOfFunctionType() {
4576            nextToken();
4577            if (token() === SyntaxKind.CloseParenToken || token() === SyntaxKind.DotDotDotToken) {
4578                // ( )
4579                // ( ...
4580                return true;
4581            }
4582            if (skipParameterStart()) {
4583                // We successfully skipped modifiers (if any) and an identifier or binding pattern,
4584                // now see if we have something that indicates a parameter declaration
4585                if (token() === SyntaxKind.ColonToken || token() === SyntaxKind.CommaToken ||
4586                    token() === SyntaxKind.QuestionToken || token() === SyntaxKind.EqualsToken) {
4587                    // ( xxx :
4588                    // ( xxx ,
4589                    // ( xxx ?
4590                    // ( xxx =
4591                    return true;
4592                }
4593                if (token() === SyntaxKind.CloseParenToken) {
4594                    nextToken();
4595                    if (token() === SyntaxKind.EqualsGreaterThanToken) {
4596                        // ( xxx ) =>
4597                        return true;
4598                    }
4599                }
4600            }
4601            return false;
4602        }
4603
4604        function parseTypeOrTypePredicate(): TypeNode {
4605            const pos = getNodePos();
4606            const typePredicateVariable = isIdentifier() && tryParse(parseTypePredicatePrefix);
4607            const type = parseType();
4608            if (typePredicateVariable) {
4609                return finishNode(factory.createTypePredicateNode(/*assertsModifier*/ undefined, typePredicateVariable, type), pos);
4610            }
4611            else {
4612                return type;
4613            }
4614        }
4615
4616        function parseTypePredicatePrefix() {
4617            const id = parseIdentifier();
4618            if (token() === SyntaxKind.IsKeyword && !scanner.hasPrecedingLineBreak()) {
4619                nextToken();
4620                return id;
4621            }
4622        }
4623
4624        function parseAssertsTypePredicate(): TypeNode {
4625            const pos = getNodePos();
4626            const assertsModifier = parseExpectedToken(SyntaxKind.AssertsKeyword);
4627            const parameterName = token() === SyntaxKind.ThisKeyword ? parseThisTypeNode() : parseIdentifier();
4628            const type = parseOptional(SyntaxKind.IsKeyword) ? parseType() : undefined;
4629            return finishNode(factory.createTypePredicateNode(assertsModifier, parameterName, type), pos);
4630        }
4631
4632        function parseType(): TypeNode {
4633            if (contextFlags & NodeFlags.TypeExcludesFlags) {
4634                return doOutsideOfContext(NodeFlags.TypeExcludesFlags, parseType);
4635            }
4636
4637            if (isStartOfFunctionTypeOrConstructorType()) {
4638                return parseFunctionOrConstructorType();
4639            }
4640            const pos = getNodePos();
4641            const type = parseUnionTypeOrHigher();
4642            if (!inDisallowConditionalTypesContext() && !scanner.hasPrecedingLineBreak() && parseOptional(SyntaxKind.ExtendsKeyword)) {
4643                // The type following 'extends' is not permitted to be another conditional type
4644                const extendsType = disallowConditionalTypesAnd(parseType);
4645                parseExpected(SyntaxKind.QuestionToken);
4646                const trueType = allowConditionalTypesAnd(parseType);
4647                parseExpected(SyntaxKind.ColonToken);
4648                const falseType = allowConditionalTypesAnd(parseType);
4649                return finishNode(factory.createConditionalTypeNode(type, extendsType, trueType, falseType), pos);
4650            }
4651            return type;
4652        }
4653
4654        function parseEtsType(pos: number, name: string): TypeNode {
4655            const contextFlagsToClear = NodeFlags.TypeExcludesFlags & contextFlags;
4656            if (contextFlagsToClear) {
4657                // clear the requested context flags
4658                setContextFlag(/*val*/ false, contextFlagsToClear);
4659                const result = parseEtsTypeReferenceWorker(pos, name);
4660                // restore the context flags we just cleared
4661                setContextFlag(/*val*/ true, contextFlagsToClear);
4662                return result;
4663            }
4664
4665            return parseEtsTypeReferenceWorker(pos, name);
4666        }
4667
4668        function parseEtsTypeReferenceWorker(pos: number, name: string): TypeNode {
4669            return finishVirtualNode(
4670                factory.createTypeReferenceNode(
4671                    finishVirtualNode(factory.createIdentifier(name), pos, pos)
4672                ),
4673                pos, pos
4674            );
4675        }
4676
4677        function parseTypeAnnotation(): TypeNode | undefined {
4678            return parseOptional(SyntaxKind.ColonToken) ? parseType() : undefined;
4679        }
4680
4681        // EXPRESSIONS
4682        function isStartOfLeftHandSideExpression(): boolean {
4683            switch (token()) {
4684                case SyntaxKind.ThisKeyword:
4685                case SyntaxKind.SuperKeyword:
4686                case SyntaxKind.NullKeyword:
4687                case SyntaxKind.TrueKeyword:
4688                case SyntaxKind.FalseKeyword:
4689                case SyntaxKind.NumericLiteral:
4690                case SyntaxKind.BigIntLiteral:
4691                case SyntaxKind.StringLiteral:
4692                case SyntaxKind.NoSubstitutionTemplateLiteral:
4693                case SyntaxKind.TemplateHead:
4694                case SyntaxKind.OpenParenToken:
4695                case SyntaxKind.OpenBracketToken:
4696                case SyntaxKind.OpenBraceToken:
4697                case SyntaxKind.FunctionKeyword:
4698                case SyntaxKind.ClassKeyword:
4699                case SyntaxKind.NewKeyword:
4700                case SyntaxKind.SlashToken:
4701                case SyntaxKind.SlashEqualsToken:
4702                case SyntaxKind.Identifier:
4703                    return true;
4704                case SyntaxKind.StructKeyword:
4705                    return inEtsContext();
4706                case SyntaxKind.ImportKeyword:
4707                    return lookAhead(nextTokenIsOpenParenOrLessThanOrDot);
4708                default:
4709                    return isIdentifier();
4710            }
4711        }
4712
4713        function isStartOfExpression(): boolean {
4714            if (isStartOfLeftHandSideExpression()) {
4715                return true;
4716            }
4717
4718            switch (token()) {
4719                case SyntaxKind.PlusToken:
4720                case SyntaxKind.MinusToken:
4721                case SyntaxKind.TildeToken:
4722                case SyntaxKind.ExclamationToken:
4723                case SyntaxKind.DeleteKeyword:
4724                case SyntaxKind.TypeOfKeyword:
4725                case SyntaxKind.VoidKeyword:
4726                case SyntaxKind.PlusPlusToken:
4727                case SyntaxKind.MinusMinusToken:
4728                case SyntaxKind.LessThanToken:
4729                case SyntaxKind.AwaitKeyword:
4730                case SyntaxKind.YieldKeyword:
4731                case SyntaxKind.PrivateIdentifier:
4732                    // Yield/await always starts an expression.  Either it is an identifier (in which case
4733                    // it is definitely an expression).  Or it's a keyword (either because we're in
4734                    // a generator or async function, or in strict mode (or both)) and it started a yield or await expression.
4735                    return true;
4736                case SyntaxKind.DotToken:
4737                    return isValidExtendOrStylesContext();
4738                default:
4739                    // Error tolerance.  If we see the start of some binary operator, we consider
4740                    // that the start of an expression.  That way we'll parse out a missing identifier,
4741                    // give a good message about an identifier being missing, and then consume the
4742                    // rest of the binary expression.
4743                    if (isBinaryOperator()) {
4744                        return true;
4745                    }
4746
4747                    return isIdentifier();
4748            }
4749        }
4750
4751        function isValidExtendOrStylesContext(): boolean {
4752            return (inEtsExtendComponentsContext() && !!extendEtsComponentDeclaration) ||
4753                (inEtsStylesComponentsContext() && !!stylesEtsComponentDeclaration);
4754        }
4755
4756        function isStartOfExpressionStatement(): boolean {
4757            // As per the grammar, none of '{' or 'function' or 'class' can start an expression statement.
4758            return token() !== SyntaxKind.OpenBraceToken &&
4759                token() !== SyntaxKind.FunctionKeyword &&
4760                token() !== SyntaxKind.ClassKeyword &&
4761                (!inEtsContext() || token() !== SyntaxKind.StructKeyword) &&
4762                token() !== SyntaxKind.AtToken &&
4763                isStartOfExpression();
4764        }
4765
4766        function parseExpression(): Expression {
4767            // Expression[in]:
4768            //      AssignmentExpression[in]
4769            //      Expression[in] , AssignmentExpression[in]
4770
4771            // clear the decorator context when parsing Expression, as it should be unambiguous when parsing a decorator
4772            const saveDecoratorContext = inDecoratorContext();
4773            if (saveDecoratorContext) {
4774                setDecoratorContext(/*val*/ false);
4775            }
4776
4777            const pos = getNodePos();
4778            let expr = parseAssignmentExpressionOrHigher(/*allowReturnTypeInArrowFunction*/ true);
4779            let operatorToken: BinaryOperatorToken;
4780            while ((operatorToken = parseOptionalToken(SyntaxKind.CommaToken))) {
4781                expr = makeBinaryExpression(expr, operatorToken, parseAssignmentExpressionOrHigher(/*allowReturnTypeInArrowFunction*/ true), pos);
4782            }
4783
4784            if (saveDecoratorContext) {
4785                setDecoratorContext(/*val*/ true);
4786            }
4787            return expr;
4788        }
4789
4790        function parseInitializer(): Expression | undefined {
4791            return parseOptional(SyntaxKind.EqualsToken) ? parseAssignmentExpressionOrHigher(/*allowReturnTypeInArrowFunction*/ true) : undefined;
4792        }
4793
4794        function parseAssignmentExpressionOrHigher(allowReturnTypeInArrowFunction: boolean): Expression {
4795            //  AssignmentExpression[in,yield]:
4796            //      1) ConditionalExpression[?in,?yield]
4797            //      2) LeftHandSideExpression = AssignmentExpression[?in,?yield]
4798            //      3) LeftHandSideExpression AssignmentOperator AssignmentExpression[?in,?yield]
4799            //      4) ArrowFunctionExpression[?in,?yield]
4800            //      5) AsyncArrowFunctionExpression[in,yield,await]
4801            //      6) [+Yield] YieldExpression[?In]
4802            //
4803            // Note: for ease of implementation we treat productions '2' and '3' as the same thing.
4804            // (i.e. they're both BinaryExpressions with an assignment operator in it).
4805
4806            // First, do the simple check if we have a YieldExpression (production '6').
4807            if (isYieldExpression()) {
4808                return parseYieldExpression();
4809            }
4810
4811            // Then, check if we have an arrow function (production '4' and '5') that starts with a parenthesized
4812            // parameter list or is an async arrow function.
4813            // AsyncArrowFunctionExpression:
4814            //      1) async[no LineTerminator here]AsyncArrowBindingIdentifier[?Yield][no LineTerminator here]=>AsyncConciseBody[?In]
4815            //      2) CoverCallExpressionAndAsyncArrowHead[?Yield, ?Await][no LineTerminator here]=>AsyncConciseBody[?In]
4816            // Production (1) of AsyncArrowFunctionExpression is parsed in "tryParseAsyncSimpleArrowFunctionExpression".
4817            // And production (2) is parsed in "tryParseParenthesizedArrowFunctionExpression".
4818            //
4819            // If we do successfully parse arrow-function, we must *not* recurse for productions 1, 2 or 3. An ArrowFunction is
4820            // not a LeftHandSideExpression, nor does it start a ConditionalExpression.  So we are done
4821            // with AssignmentExpression if we see one.
4822            const arrowExpression = tryParseParenthesizedArrowFunctionExpression(allowReturnTypeInArrowFunction) || tryParseAsyncSimpleArrowFunctionExpression(allowReturnTypeInArrowFunction);
4823            if (arrowExpression) {
4824                return arrowExpression;
4825            }
4826
4827            // Now try to see if we're in production '1', '2' or '3'.  A conditional expression can
4828            // start with a LogicalOrExpression, while the assignment productions can only start with
4829            // LeftHandSideExpressions.
4830            //
4831            // So, first, we try to just parse out a BinaryExpression.  If we get something that is a
4832            // LeftHandSide or higher, then we can try to parse out the assignment expression part.
4833            // Otherwise, we try to parse out the conditional expression bit.  We want to allow any
4834            // binary expression here, so we pass in the 'lowest' precedence here so that it matches
4835            // and consumes anything.
4836            const pos = getNodePos();
4837            const expr = parseBinaryExpressionOrHigher(OperatorPrecedence.Lowest);
4838
4839            // To avoid a look-ahead, we did not handle the case of an arrow function with a single un-parenthesized
4840            // parameter ('x => ...') above. We handle it here by checking if the parsed expression was a single
4841            // identifier and the current token is an arrow.
4842            if (expr.kind === SyntaxKind.Identifier && token() === SyntaxKind.EqualsGreaterThanToken) {
4843                return parseSimpleArrowFunctionExpression(pos, expr as Identifier, allowReturnTypeInArrowFunction, /*asyncModifier*/ undefined);
4844            }
4845
4846            // Now see if we might be in cases '2' or '3'.
4847            // If the expression was a LHS expression, and we have an assignment operator, then
4848            // we're in '2' or '3'. Consume the assignment and return.
4849            //
4850            // Note: we call reScanGreaterToken so that we get an appropriately merged token
4851            // for cases like `> > =` becoming `>>=`
4852            if (isLeftHandSideExpression(expr) && isAssignmentOperator(reScanGreaterToken())) {
4853                return makeBinaryExpression(expr, parseTokenNode(), parseAssignmentExpressionOrHigher(allowReturnTypeInArrowFunction), pos);
4854            }
4855
4856            // It's a CallExpression with open brace followed, therefore, we think it's an EtsComponentExpression
4857            if ((inBuildContext() || inBuilderContext()) && inUICallbackContext() && ts.isCallExpression(expr) && token() === SyntaxKind.OpenBraceToken) {
4858                return makeEtsComponentExpression(expr, pos);
4859            }
4860
4861            // It wasn't an assignment or a lambda.  This is a conditional expression:
4862            return parseConditionalExpressionRest(expr, pos, allowReturnTypeInArrowFunction);
4863        }
4864
4865        function makeEtsComponentExpression(expression: Expression, pos: number): EtsComponentExpression {
4866            const name = (<CallExpression>expression).expression;
4867            const body = parseFunctionBlock(SignatureFlags.None);
4868            return finishNode(factory.createEtsComponentExpression(<Identifier>name, (<CallExpression>expression).arguments, body), pos);
4869        }
4870
4871        function isYieldExpression(): boolean {
4872            if (token() === SyntaxKind.YieldKeyword) {
4873                // If we have a 'yield' keyword, and this is a context where yield expressions are
4874                // allowed, then definitely parse out a yield expression.
4875                if (inYieldContext()) {
4876                    return true;
4877                }
4878
4879                // We're in a context where 'yield expr' is not allowed.  However, if we can
4880                // definitely tell that the user was trying to parse a 'yield expr' and not
4881                // just a normal expr that start with a 'yield' identifier, then parse out
4882                // a 'yield expr'.  We can then report an error later that they are only
4883                // allowed in generator expressions.
4884                //
4885                // for example, if we see 'yield(foo)', then we'll have to treat that as an
4886                // invocation expression of something called 'yield'.  However, if we have
4887                // 'yield foo' then that is not legal as a normal expression, so we can
4888                // definitely recognize this as a yield expression.
4889                //
4890                // for now we just check if the next token is an identifier.  More heuristics
4891                // can be added here later as necessary.  We just need to make sure that we
4892                // don't accidentally consume something legal.
4893                return lookAhead(nextTokenIsIdentifierOrKeywordOrLiteralOnSameLine);
4894            }
4895
4896            return false;
4897        }
4898
4899        function nextTokenIsIdentifierOnSameLine() {
4900            nextToken();
4901            return !scanner.hasPrecedingLineBreak() && isIdentifier();
4902        }
4903
4904        function parseYieldExpression(): YieldExpression {
4905            const pos = getNodePos();
4906
4907            // YieldExpression[In] :
4908            //      yield
4909            //      yield [no LineTerminator here] [Lexical goal InputElementRegExp]AssignmentExpression[?In, Yield]
4910            //      yield [no LineTerminator here] * [Lexical goal InputElementRegExp]AssignmentExpression[?In, Yield]
4911            nextToken();
4912
4913            if (!scanner.hasPrecedingLineBreak() &&
4914                (token() === SyntaxKind.AsteriskToken || isStartOfExpression())) {
4915                return finishNode(
4916                    factory.createYieldExpression(
4917                        parseOptionalToken(SyntaxKind.AsteriskToken),
4918                        parseAssignmentExpressionOrHigher(/*allowReturnTypeInArrowFunction*/ true)
4919                    ),
4920                    pos
4921                );
4922            }
4923            else {
4924                // if the next token is not on the same line as yield.  or we don't have an '*' or
4925                // the start of an expression, then this is just a simple "yield" expression.
4926                return finishNode(factory.createYieldExpression(/*asteriskToken*/ undefined, /*expression*/ undefined), pos);
4927            }
4928        }
4929
4930        function parseSimpleArrowFunctionExpression(pos: number, identifier: Identifier, allowReturnTypeInArrowFunction: boolean, asyncModifier?: NodeArray<Modifier> | undefined): ArrowFunction {
4931            Debug.assert(token() === SyntaxKind.EqualsGreaterThanToken, "parseSimpleArrowFunctionExpression should only have been called if we had a =>");
4932            const parameter = factory.createParameterDeclaration(
4933                /*modifiers*/ undefined,
4934                /*dotDotDotToken*/ undefined,
4935                identifier,
4936                /*questionToken*/ undefined,
4937                /*type*/ undefined,
4938                /*initializer*/ undefined
4939            );
4940            finishNode(parameter, identifier.pos);
4941
4942            const parameters = createNodeArray<ParameterDeclaration>([parameter], parameter.pos, parameter.end);
4943            const equalsGreaterThanToken = parseExpectedToken(SyntaxKind.EqualsGreaterThanToken);
4944            const body = parseArrowFunctionExpressionBody(/*isAsync*/ !!asyncModifier, allowReturnTypeInArrowFunction);
4945            const node = factory.createArrowFunction(asyncModifier, /*typeParameters*/ undefined, parameters, /*type*/ undefined, equalsGreaterThanToken, body);
4946            return addJSDocComment(finishNode(node, pos));
4947        }
4948
4949        function tryParseParenthesizedArrowFunctionExpression(allowReturnTypeInArrowFunction: boolean): Expression | undefined {
4950            const triState = isParenthesizedArrowFunctionExpression();
4951            if (triState === Tristate.False) {
4952                // It's definitely not a parenthesized arrow function expression.
4953                return undefined;
4954            }
4955
4956            // If we definitely have an arrow function, then we can just parse one, not requiring a
4957            // following => or { token. Otherwise, we *might* have an arrow function.  Try to parse
4958            // it out, but don't allow any ambiguity, and return 'undefined' if this could be an
4959            // expression instead.
4960            return triState === Tristate.True ?
4961                parseParenthesizedArrowFunctionExpression(/*allowAmbiguity*/ true, /*allowReturnTypeInArrowFunction*/ true) :
4962                tryParse(() => parsePossibleParenthesizedArrowFunctionExpression(allowReturnTypeInArrowFunction));
4963        }
4964
4965        //  True        -> We definitely expect a parenthesized arrow function here.
4966        //  False       -> There *cannot* be a parenthesized arrow function here.
4967        //  Unknown     -> There *might* be a parenthesized arrow function here.
4968        //                 Speculatively look ahead to be sure, and rollback if not.
4969        function isParenthesizedArrowFunctionExpression(): Tristate {
4970            if (token() === SyntaxKind.OpenParenToken || token() === SyntaxKind.LessThanToken || token() === SyntaxKind.AsyncKeyword) {
4971                return lookAhead(isParenthesizedArrowFunctionExpressionWorker);
4972            }
4973
4974            if (token() === SyntaxKind.EqualsGreaterThanToken) {
4975                // ERROR RECOVERY TWEAK:
4976                // If we see a standalone => try to parse it as an arrow function expression as that's
4977                // likely what the user intended to write.
4978                return Tristate.True;
4979            }
4980            // Definitely not a parenthesized arrow function.
4981            return Tristate.False;
4982        }
4983
4984        function isParenthesizedArrowFunctionExpressionWorker() {
4985            if (token() === SyntaxKind.AsyncKeyword) {
4986                nextToken();
4987                if (scanner.hasPrecedingLineBreak()) {
4988                    return Tristate.False;
4989                }
4990                if (token() !== SyntaxKind.OpenParenToken && token() !== SyntaxKind.LessThanToken) {
4991                    return Tristate.False;
4992                }
4993            }
4994
4995            const first = token();
4996            const second = nextToken();
4997
4998            if (first === SyntaxKind.OpenParenToken) {
4999                if (second === SyntaxKind.CloseParenToken) {
5000                    // Simple cases: "() =>", "(): ", and "() {".
5001                    // This is an arrow function with no parameters.
5002                    // The last one is not actually an arrow function,
5003                    // but this is probably what the user intended.
5004                    const third = nextToken();
5005                    switch (third) {
5006                        case SyntaxKind.EqualsGreaterThanToken:
5007                        case SyntaxKind.ColonToken:
5008                        case SyntaxKind.OpenBraceToken:
5009                            return Tristate.True;
5010                        default:
5011                            return Tristate.False;
5012                    }
5013                }
5014
5015                // If encounter "([" or "({", this could be the start of a binding pattern.
5016                // Examples:
5017                //      ([ x ]) => { }
5018                //      ({ x }) => { }
5019                //      ([ x ])
5020                //      ({ x })
5021                if (second === SyntaxKind.OpenBracketToken || second === SyntaxKind.OpenBraceToken) {
5022                    return Tristate.Unknown;
5023                }
5024
5025                // Simple case: "(..."
5026                // This is an arrow function with a rest parameter.
5027                if (second === SyntaxKind.DotDotDotToken) {
5028                    return Tristate.True;
5029                }
5030
5031                // Check for "(xxx yyy", where xxx is a modifier and yyy is an identifier. This
5032                // isn't actually allowed, but we want to treat it as a lambda so we can provide
5033                // a good error message.
5034                if (isModifierKind(second) && second !== SyntaxKind.AsyncKeyword && lookAhead(nextTokenIsIdentifier)) {
5035                    if (nextToken() === SyntaxKind.AsKeyword) {
5036                        // https://github.com/microsoft/TypeScript/issues/44466
5037                        return Tristate.False;
5038                    }
5039                    return Tristate.True;
5040                }
5041
5042                // If we had "(" followed by something that's not an identifier,
5043                // then this definitely doesn't look like a lambda.  "this" is not
5044                // valid, but we want to parse it and then give a semantic error.
5045                if (!isIdentifier() && second !== SyntaxKind.ThisKeyword) {
5046                    return Tristate.False;
5047                }
5048
5049                switch (nextToken()) {
5050                    case SyntaxKind.ColonToken:
5051                        // If we have something like "(a:", then we must have a
5052                        // type-annotated parameter in an arrow function expression.
5053                        return Tristate.True;
5054                    case SyntaxKind.QuestionToken:
5055                        nextToken();
5056                        // If we have "(a?:" or "(a?," or "(a?=" or "(a?)" then it is definitely a lambda.
5057                        if (token() === SyntaxKind.ColonToken || token() === SyntaxKind.CommaToken || token() === SyntaxKind.EqualsToken || token() === SyntaxKind.CloseParenToken) {
5058                            return Tristate.True;
5059                        }
5060                        // Otherwise it is definitely not a lambda.
5061                        return Tristate.False;
5062                    case SyntaxKind.CommaToken:
5063                    case SyntaxKind.EqualsToken:
5064                    case SyntaxKind.CloseParenToken:
5065                        // If we have "(a," or "(a=" or "(a)" this *could* be an arrow function
5066                        return Tristate.Unknown;
5067                }
5068                // It is definitely not an arrow function
5069                return Tristate.False;
5070            }
5071            else {
5072                Debug.assert(first === SyntaxKind.LessThanToken);
5073
5074                // If we have "<" not followed by an identifier,
5075                // then this definitely is not an arrow function.
5076                if (!isIdentifier()) {
5077                    return Tristate.False;
5078                }
5079
5080                // JSX overrides
5081                if (languageVariant === LanguageVariant.JSX) {
5082                    const isArrowFunctionInJsx = lookAhead(() => {
5083                        const third = nextToken();
5084                        if (third === SyntaxKind.ExtendsKeyword) {
5085                            const fourth = nextToken();
5086                            switch (fourth) {
5087                                case SyntaxKind.EqualsToken:
5088                                case SyntaxKind.GreaterThanToken:
5089                                    return false;
5090                                default:
5091                                    return true;
5092                            }
5093                        }
5094                        else if (third === SyntaxKind.CommaToken || third === SyntaxKind.EqualsToken) {
5095                            return true;
5096                        }
5097                        return false;
5098                    });
5099
5100                    if (isArrowFunctionInJsx) {
5101                        return Tristate.True;
5102                    }
5103
5104                    return Tristate.False;
5105                }
5106
5107                // This *could* be a parenthesized arrow function.
5108                return Tristate.Unknown;
5109            }
5110        }
5111
5112        function parsePossibleParenthesizedArrowFunctionExpression(allowReturnTypeInArrowFunction: boolean): ArrowFunction | undefined {
5113            const tokenPos = scanner.getTokenPos();
5114            if (notParenthesizedArrow?.has(tokenPos)) {
5115                return undefined;
5116            }
5117
5118            const result = parseParenthesizedArrowFunctionExpression(/*allowAmbiguity*/ false, allowReturnTypeInArrowFunction);
5119            if (!result) {
5120                (notParenthesizedArrow || (notParenthesizedArrow = new Set())).add(tokenPos);
5121            }
5122
5123            return result;
5124        }
5125
5126        function tryParseAsyncSimpleArrowFunctionExpression(allowReturnTypeInArrowFunction: boolean): ArrowFunction | undefined {
5127            // We do a check here so that we won't be doing unnecessarily call to "lookAhead"
5128            if (token() === SyntaxKind.AsyncKeyword) {
5129                if (lookAhead(isUnParenthesizedAsyncArrowFunctionWorker) === Tristate.True) {
5130                    const pos = getNodePos();
5131                    const asyncModifier = parseModifiersForArrowFunction();
5132                    const expr = parseBinaryExpressionOrHigher(OperatorPrecedence.Lowest);
5133                    return parseSimpleArrowFunctionExpression(pos, expr as Identifier, allowReturnTypeInArrowFunction, asyncModifier);
5134                }
5135            }
5136            return undefined;
5137        }
5138
5139        function isUnParenthesizedAsyncArrowFunctionWorker(): Tristate {
5140            // AsyncArrowFunctionExpression:
5141            //      1) async[no LineTerminator here]AsyncArrowBindingIdentifier[?Yield][no LineTerminator here]=>AsyncConciseBody[?In]
5142            //      2) CoverCallExpressionAndAsyncArrowHead[?Yield, ?Await][no LineTerminator here]=>AsyncConciseBody[?In]
5143            if (token() === SyntaxKind.AsyncKeyword) {
5144                nextToken();
5145                // If the "async" is followed by "=>" token then it is not a beginning of an async arrow-function
5146                // but instead a simple arrow-function which will be parsed inside "parseAssignmentExpressionOrHigher"
5147                if (scanner.hasPrecedingLineBreak() || token() === SyntaxKind.EqualsGreaterThanToken) {
5148                    return Tristate.False;
5149                }
5150                // Check for un-parenthesized AsyncArrowFunction
5151                const expr = parseBinaryExpressionOrHigher(OperatorPrecedence.Lowest);
5152                if (!scanner.hasPrecedingLineBreak() && expr.kind === SyntaxKind.Identifier && token() === SyntaxKind.EqualsGreaterThanToken) {
5153                    return Tristate.True;
5154                }
5155            }
5156
5157            return Tristate.False;
5158        }
5159
5160        function parseParenthesizedArrowFunctionExpression(allowAmbiguity: boolean, allowReturnTypeInArrowFunction: boolean): ArrowFunction | undefined {
5161            const pos = getNodePos();
5162            const hasJSDoc = hasPrecedingJSDocComment();
5163            const modifiers = parseModifiersForArrowFunction();
5164            const isAsync = some(modifiers, isAsyncModifier) ? SignatureFlags.Await : SignatureFlags.None;
5165            // Arrow functions are never generators.
5166            //
5167            // If we're speculatively parsing a signature for a parenthesized arrow function, then
5168            // we have to have a complete parameter list.  Otherwise we might see something like
5169            // a => (b => c)
5170            // And think that "(b =>" was actually a parenthesized arrow function with a missing
5171            // close paren.
5172            const typeParameters = parseTypeParameters();
5173
5174            let parameters: NodeArray<ParameterDeclaration>;
5175            if (!parseExpected(SyntaxKind.OpenParenToken)) {
5176                if (!allowAmbiguity) {
5177                    return undefined;
5178                }
5179                parameters = createMissingList<ParameterDeclaration>();
5180            }
5181            else {
5182                if (!allowAmbiguity) {
5183                    const maybeParameters = parseParametersWorker(isAsync, allowAmbiguity);
5184                    if (!maybeParameters) {
5185                        return undefined;
5186                    }
5187                    parameters = maybeParameters;
5188                }
5189                else {
5190                    parameters = parseParametersWorker(isAsync, allowAmbiguity);
5191                }
5192                if (!parseExpected(SyntaxKind.CloseParenToken) && !allowAmbiguity) {
5193                    return undefined;
5194                }
5195            }
5196
5197            const hasReturnColon = token() === SyntaxKind.ColonToken;
5198            const type = parseReturnType(SyntaxKind.ColonToken, /*isType*/ false);
5199            if (type && !allowAmbiguity && typeHasArrowFunctionBlockingParseError(type)) {
5200                return undefined;
5201            }
5202
5203            // Parsing a signature isn't enough.
5204            // Parenthesized arrow signatures often look like other valid expressions.
5205            // For instance:
5206            //  - "(x = 10)" is an assignment expression parsed as a signature with a default parameter value.
5207            //  - "(x,y)" is a comma expression parsed as a signature with two parameters.
5208            //  - "a ? (b): c" will have "(b):" parsed as a signature with a return type annotation.
5209            //  - "a ? (b): function() {}" will too, since function() is a valid JSDoc function type.
5210            //  - "a ? (b): (function() {})" as well, but inside of a parenthesized type with an arbitrary amount of nesting.
5211            //
5212            // So we need just a bit of lookahead to ensure that it can only be a signature.
5213
5214            let unwrappedType = type;
5215            while (unwrappedType?.kind === SyntaxKind.ParenthesizedType) {
5216                unwrappedType = (unwrappedType as ParenthesizedTypeNode).type;  // Skip parens if need be
5217            }
5218
5219            const hasJSDocFunctionType = unwrappedType && isJSDocFunctionType(unwrappedType);
5220            if (!allowAmbiguity && token() !== SyntaxKind.EqualsGreaterThanToken && (hasJSDocFunctionType || token() !== SyntaxKind.OpenBraceToken)) {
5221                // Returning undefined here will cause our caller to rewind to where we started from.
5222                    return undefined;
5223            }
5224
5225            // If we have an arrow, then try to parse the body. Even if not, try to parse if we
5226            // have an opening brace, just in case we're in an error state.
5227            const lastToken = token();
5228            const equalsGreaterThanToken = parseExpectedToken(SyntaxKind.EqualsGreaterThanToken);
5229            let originUIContextFlag = inUICallbackContext()
5230            setUICallbackContext(inSyntaxComponentContext() ? true : false);
5231            setSyntaxComponentContext(false);
5232            const body = (lastToken === SyntaxKind.EqualsGreaterThanToken || lastToken === SyntaxKind.OpenBraceToken)
5233                ? parseArrowFunctionExpressionBody(some(modifiers, isAsyncModifier), allowReturnTypeInArrowFunction)
5234                : parseIdentifier();
5235            setUICallbackContext(originUIContextFlag);
5236            // Given:
5237            //     x ? y => ({ y }) : z => ({ z })
5238            // We try to parse the body of the first arrow function by looking at:
5239            //     ({ y }) : z => ({ z })
5240            // This is a valid arrow function with "z" as the return type.
5241            //
5242            // But, if we're in the true side of a conditional expression, this colon
5243            // terminates the expression, so we cannot allow a return type if we aren't
5244            // certain whether or not the preceding text was parsed as a parameter list.
5245            //
5246            // For example,
5247            //     a() ? (b: number, c?: string): void => d() : e
5248            // is determined by isParenthesizedArrowFunctionExpression to unambiguously
5249            // be an arrow expression, so we allow a return type.
5250            if (!allowReturnTypeInArrowFunction && hasReturnColon) {
5251                // However, if the arrow function we were able to parse is followed by another colon
5252                // as in:
5253                //     a ? (x): string => x : null
5254                // Then allow the arrow function, and treat the second colon as terminating
5255                // the conditional expression. It's okay to do this because this code would
5256                // be a syntax error in JavaScript (as the second colon shouldn't be there).
5257                if (token() !== SyntaxKind.ColonToken) {
5258                    return undefined;
5259                }
5260            }
5261
5262            const node = factory.createArrowFunction(modifiers, typeParameters, parameters, type, equalsGreaterThanToken, body);
5263            return withJSDoc(finishNode(node, pos), hasJSDoc);
5264        }
5265
5266        function parseArrowFunctionExpressionBody(isAsync: boolean, allowReturnTypeInArrowFunction: boolean): Block | Expression {
5267            if (token() === SyntaxKind.OpenBraceToken) {
5268                return parseFunctionBlock(isAsync ? SignatureFlags.Await : SignatureFlags.None);
5269            }
5270
5271            if (token() !== SyntaxKind.SemicolonToken &&
5272                token() !== SyntaxKind.FunctionKeyword &&
5273                token() !== SyntaxKind.ClassKeyword &&
5274                (!inEtsContext() || token() !== SyntaxKind.StructKeyword) &&
5275                isStartOfStatement() &&
5276                !isStartOfExpressionStatement()) {
5277                // Check if we got a plain statement (i.e. no expression-statements, no function/class expressions/declarations)
5278                //
5279                // Here we try to recover from a potential error situation in the case where the
5280                // user meant to supply a block. For example, if the user wrote:
5281                //
5282                //  a =>
5283                //      let v = 0;
5284                //  }
5285                //
5286                // they may be missing an open brace.  Check to see if that's the case so we can
5287                // try to recover better.  If we don't do this, then the next close curly we see may end
5288                // up preemptively closing the containing construct.
5289                //
5290                // Note: even when 'IgnoreMissingOpenBrace' is passed, parseBody will still error.
5291                return parseFunctionBlock(SignatureFlags.IgnoreMissingOpenBrace | (isAsync ? SignatureFlags.Await : SignatureFlags.None));
5292            }
5293
5294            const savedTopLevel = topLevel;
5295            topLevel = false;
5296            const node = isAsync
5297                ? doInAwaitContext(() => parseAssignmentExpressionOrHigher(allowReturnTypeInArrowFunction))
5298                : doOutsideOfAwaitContext(() => parseAssignmentExpressionOrHigher(allowReturnTypeInArrowFunction));
5299            topLevel = savedTopLevel;
5300            return node;
5301        }
5302
5303        function parseConditionalExpressionRest(leftOperand: Expression, pos: number, allowReturnTypeInArrowFunction: boolean): Expression {
5304            // Note: we are passed in an expression which was produced from parseBinaryExpressionOrHigher.
5305            const questionToken = parseOptionalToken(SyntaxKind.QuestionToken);
5306            if (!questionToken) {
5307                return leftOperand;
5308            }
5309
5310            // Note: we explicitly 'allowIn' in the whenTrue part of the condition expression, and
5311            // we do not that for the 'whenFalse' part.
5312            let colonToken;
5313            return finishNode(
5314                factory.createConditionalExpression(
5315                    leftOperand,
5316                    questionToken,
5317                    doOutsideOfContext(disallowInAndDecoratorContext, () => parseAssignmentExpressionOrHigher(/*allowReturnTypeInArrowFunction*/ false)),
5318                    colonToken = parseExpectedToken(SyntaxKind.ColonToken),
5319                    nodeIsPresent(colonToken)
5320                        ? parseAssignmentExpressionOrHigher(allowReturnTypeInArrowFunction)
5321                        : createMissingNode(SyntaxKind.Identifier, /*reportAtCurrentPosition*/ false, Diagnostics._0_expected, tokenToString(SyntaxKind.ColonToken))
5322                ),
5323                pos
5324            );
5325        }
5326
5327        function parseBinaryExpressionOrHigher(precedence: OperatorPrecedence): Expression {
5328            const pos = getNodePos();
5329            const leftOperand = parseUnaryExpressionOrHigher();
5330            return parseBinaryExpressionRest(precedence, leftOperand, pos);
5331        }
5332
5333        function isInOrOfKeyword(t: SyntaxKind) {
5334            return t === SyntaxKind.InKeyword || t === SyntaxKind.OfKeyword;
5335        }
5336
5337        function parseBinaryExpressionRest(precedence: OperatorPrecedence, leftOperand: Expression, pos: number): Expression {
5338            while (true) {
5339                // We either have a binary operator here, or we're finished.  We call
5340                // reScanGreaterToken so that we merge token sequences like > and = into >=
5341
5342                reScanGreaterToken();
5343                const newPrecedence = getBinaryOperatorPrecedence(token());
5344
5345                // Check the precedence to see if we should "take" this operator
5346                // - For left associative operator (all operator but **), consume the operator,
5347                //   recursively call the function below, and parse binaryExpression as a rightOperand
5348                //   of the caller if the new precedence of the operator is greater then or equal to the current precedence.
5349                //   For example:
5350                //      a - b - c;
5351                //            ^token; leftOperand = b. Return b to the caller as a rightOperand
5352                //      a * b - c
5353                //            ^token; leftOperand = b. Return b to the caller as a rightOperand
5354                //      a - b * c;
5355                //            ^token; leftOperand = b. Return b * c to the caller as a rightOperand
5356                // - For right associative operator (**), consume the operator, recursively call the function
5357                //   and parse binaryExpression as a rightOperand of the caller if the new precedence of
5358                //   the operator is strictly grater than the current precedence
5359                //   For example:
5360                //      a ** b ** c;
5361                //             ^^token; leftOperand = b. Return b ** c to the caller as a rightOperand
5362                //      a - b ** c;
5363                //            ^^token; leftOperand = b. Return b ** c to the caller as a rightOperand
5364                //      a ** b - c
5365                //             ^token; leftOperand = b. Return b to the caller as a rightOperand
5366                const consumeCurrentOperator = token() === SyntaxKind.AsteriskAsteriskToken ?
5367                    newPrecedence >= precedence :
5368                    newPrecedence > precedence;
5369
5370                if (!consumeCurrentOperator) {
5371                    break;
5372                }
5373
5374                if (token() === SyntaxKind.InKeyword && inDisallowInContext()) {
5375                    break;
5376                }
5377
5378                if (token() === SyntaxKind.AsKeyword || token() === SyntaxKind.SatisfiesKeyword) {
5379                    // Make sure we *do* perform ASI for constructs like this:
5380                    //    var x = foo
5381                    //    as (Bar)
5382                    // This should be parsed as an initialized variable, followed
5383                    // by a function call to 'as' with the argument 'Bar'
5384                    if (scanner.hasPrecedingLineBreak()) {
5385                        break;
5386                    }
5387                    else {
5388                        const keywordKind = token();
5389                        nextToken();
5390                        leftOperand = keywordKind === SyntaxKind.SatisfiesKeyword ? makeSatisfiesExpression(leftOperand, parseType()) :
5391                            makeAsExpression(leftOperand, parseType());
5392                    }
5393                }
5394                else {
5395                    leftOperand = makeBinaryExpression(leftOperand, parseTokenNode(), parseBinaryExpressionOrHigher(newPrecedence), pos);
5396                }
5397            }
5398
5399            return leftOperand;
5400        }
5401
5402        function isBinaryOperator() {
5403            if (inDisallowInContext() && token() === SyntaxKind.InKeyword) {
5404                return false;
5405            }
5406
5407            return getBinaryOperatorPrecedence(token()) > 0;
5408        }
5409
5410        function makeSatisfiesExpression(left: Expression, right: TypeNode): SatisfiesExpression {
5411            return finishNode(factory.createSatisfiesExpression(left, right), left.pos);
5412        }
5413
5414        function makeBinaryExpression(left: Expression, operatorToken: BinaryOperatorToken, right: Expression, pos: number): BinaryExpression {
5415            return finishNode(factory.createBinaryExpression(left, operatorToken, right), pos);
5416        }
5417
5418        function makeAsExpression(left: Expression, right: TypeNode): AsExpression {
5419            return finishNode(factory.createAsExpression(left, right), left.pos);
5420        }
5421
5422        function parsePrefixUnaryExpression() {
5423            const pos = getNodePos();
5424            return finishNode(factory.createPrefixUnaryExpression(token() as PrefixUnaryOperator, nextTokenAnd(parseSimpleUnaryExpression)), pos);
5425        }
5426
5427        function parseDeleteExpression() {
5428            const pos = getNodePos();
5429            return finishNode(factory.createDeleteExpression(nextTokenAnd(parseSimpleUnaryExpression)), pos);
5430        }
5431
5432        function parseTypeOfExpression() {
5433            const pos = getNodePos();
5434            return finishNode(factory.createTypeOfExpression(nextTokenAnd(parseSimpleUnaryExpression)), pos);
5435        }
5436
5437        function parseVoidExpression() {
5438            const pos = getNodePos();
5439            return finishNode(factory.createVoidExpression(nextTokenAnd(parseSimpleUnaryExpression)), pos);
5440        }
5441
5442        function isAwaitExpression(): boolean {
5443            if (token() === SyntaxKind.AwaitKeyword) {
5444                if (inAwaitContext()) {
5445                    return true;
5446                }
5447
5448                // here we are using similar heuristics as 'isYieldExpression'
5449                return lookAhead(nextTokenIsIdentifierOrKeywordOrLiteralOnSameLine);
5450            }
5451
5452            return false;
5453        }
5454
5455        function parseAwaitExpression() {
5456            const pos = getNodePos();
5457            return finishNode(factory.createAwaitExpression(nextTokenAnd(parseSimpleUnaryExpression)), pos);
5458        }
5459
5460        /**
5461         * Parse ES7 exponential expression and await expression
5462         *
5463         * ES7 ExponentiationExpression:
5464         *      1) UnaryExpression[?Yield]
5465         *      2) UpdateExpression[?Yield] ** ExponentiationExpression[?Yield]
5466         *
5467         */
5468        function parseUnaryExpressionOrHigher(): UnaryExpression | BinaryExpression {
5469            /**
5470             * ES7 UpdateExpression:
5471             *      1) LeftHandSideExpression[?Yield]
5472             *      2) LeftHandSideExpression[?Yield][no LineTerminator here]++
5473             *      3) LeftHandSideExpression[?Yield][no LineTerminator here]--
5474             *      4) ++UnaryExpression[?Yield]
5475             *      5) --UnaryExpression[?Yield]
5476             */
5477            if (isUpdateExpression()) {
5478                const pos = getNodePos();
5479                const updateExpression = parseUpdateExpression();
5480                return token() === SyntaxKind.AsteriskAsteriskToken ?
5481                    parseBinaryExpressionRest(getBinaryOperatorPrecedence(token()), updateExpression, pos) as BinaryExpression :
5482                    updateExpression;
5483            }
5484
5485            /**
5486             * ES7 UnaryExpression:
5487             *      1) UpdateExpression[?yield]
5488             *      2) delete UpdateExpression[?yield]
5489             *      3) void UpdateExpression[?yield]
5490             *      4) typeof UpdateExpression[?yield]
5491             *      5) + UpdateExpression[?yield]
5492             *      6) - UpdateExpression[?yield]
5493             *      7) ~ UpdateExpression[?yield]
5494             *      8) ! UpdateExpression[?yield]
5495             */
5496            const unaryOperator = token();
5497            const simpleUnaryExpression = parseSimpleUnaryExpression();
5498            if (token() === SyntaxKind.AsteriskAsteriskToken) {
5499                const pos = skipTrivia(sourceText, simpleUnaryExpression.pos);
5500                const { end } = simpleUnaryExpression;
5501                if (simpleUnaryExpression.kind === SyntaxKind.TypeAssertionExpression) {
5502                    parseErrorAt(pos, end, Diagnostics.A_type_assertion_expression_is_not_allowed_in_the_left_hand_side_of_an_exponentiation_expression_Consider_enclosing_the_expression_in_parentheses);
5503                }
5504                else {
5505                    parseErrorAt(pos, end, Diagnostics.An_unary_expression_with_the_0_operator_is_not_allowed_in_the_left_hand_side_of_an_exponentiation_expression_Consider_enclosing_the_expression_in_parentheses, tokenToString(unaryOperator));
5506                }
5507            }
5508            return simpleUnaryExpression;
5509        }
5510
5511        /**
5512         * Parse ES7 simple-unary expression or higher:
5513         *
5514         * ES7 UnaryExpression:
5515         *      1) UpdateExpression[?yield]
5516         *      2) delete UnaryExpression[?yield]
5517         *      3) void UnaryExpression[?yield]
5518         *      4) typeof UnaryExpression[?yield]
5519         *      5) + UnaryExpression[?yield]
5520         *      6) - UnaryExpression[?yield]
5521         *      7) ~ UnaryExpression[?yield]
5522         *      8) ! UnaryExpression[?yield]
5523         *      9) [+Await] await UnaryExpression[?yield]
5524         */
5525        function parseSimpleUnaryExpression(): UnaryExpression {
5526            switch (token()) {
5527                case SyntaxKind.PlusToken:
5528                case SyntaxKind.MinusToken:
5529                case SyntaxKind.TildeToken:
5530                case SyntaxKind.ExclamationToken:
5531                    return parsePrefixUnaryExpression();
5532                case SyntaxKind.DeleteKeyword:
5533                    return parseDeleteExpression();
5534                case SyntaxKind.TypeOfKeyword:
5535                    return parseTypeOfExpression();
5536                case SyntaxKind.VoidKeyword:
5537                    return parseVoidExpression();
5538                case SyntaxKind.LessThanToken:
5539                    // This is modified UnaryExpression grammar in TypeScript
5540                    //  UnaryExpression (modified):
5541                    //      < type > UnaryExpression
5542                    return parseTypeAssertion();
5543                case SyntaxKind.AwaitKeyword:
5544                    if (isAwaitExpression()) {
5545                        return parseAwaitExpression();
5546                    }
5547                    // falls through
5548                default:
5549                    return parseUpdateExpression();
5550            }
5551        }
5552
5553        /**
5554         * Check if the current token can possibly be an ES7 increment expression.
5555         *
5556         * ES7 UpdateExpression:
5557         *      LeftHandSideExpression[?Yield]
5558         *      LeftHandSideExpression[?Yield][no LineTerminator here]++
5559         *      LeftHandSideExpression[?Yield][no LineTerminator here]--
5560         *      ++LeftHandSideExpression[?Yield]
5561         *      --LeftHandSideExpression[?Yield]
5562         */
5563        function isUpdateExpression(): boolean {
5564            // This function is called inside parseUnaryExpression to decide
5565            // whether to call parseSimpleUnaryExpression or call parseUpdateExpression directly
5566            switch (token()) {
5567                case SyntaxKind.PlusToken:
5568                case SyntaxKind.MinusToken:
5569                case SyntaxKind.TildeToken:
5570                case SyntaxKind.ExclamationToken:
5571                case SyntaxKind.DeleteKeyword:
5572                case SyntaxKind.TypeOfKeyword:
5573                case SyntaxKind.VoidKeyword:
5574                case SyntaxKind.AwaitKeyword:
5575                    return false;
5576                case SyntaxKind.LessThanToken:
5577                    // If we are not in JSX context, we are parsing TypeAssertion which is an UnaryExpression
5578                    if (languageVariant !== LanguageVariant.JSX) {
5579                        return false;
5580                    }
5581                    // We are in JSX context and the token is part of JSXElement.
5582                    // falls through
5583                default:
5584                    return true;
5585            }
5586        }
5587
5588        /**
5589         * Parse ES7 UpdateExpression. UpdateExpression is used instead of ES6's PostFixExpression.
5590         *
5591         * ES7 UpdateExpression[yield]:
5592         *      1) LeftHandSideExpression[?yield]
5593         *      2) LeftHandSideExpression[?yield] [[no LineTerminator here]]++
5594         *      3) LeftHandSideExpression[?yield] [[no LineTerminator here]]--
5595         *      4) ++LeftHandSideExpression[?yield]
5596         *      5) --LeftHandSideExpression[?yield]
5597         * In TypeScript (2), (3) are parsed as PostfixUnaryExpression. (4), (5) are parsed as PrefixUnaryExpression
5598         */
5599        function parseUpdateExpression(): UpdateExpression {
5600            if (token() === SyntaxKind.PlusPlusToken || token() === SyntaxKind.MinusMinusToken) {
5601                const pos = getNodePos();
5602                return finishNode(factory.createPrefixUnaryExpression(token() as PrefixUnaryOperator, nextTokenAnd(parseLeftHandSideExpressionOrHigher)), pos);
5603            }
5604            else if (languageVariant === LanguageVariant.JSX && token() === SyntaxKind.LessThanToken && lookAhead(nextTokenIsIdentifierOrKeywordOrGreaterThan)) {
5605                // JSXElement is part of primaryExpression
5606                return parseJsxElementOrSelfClosingElementOrFragment(/*inExpressionContext*/ true);
5607            }
5608
5609            const expression = parseLeftHandSideExpressionOrHigher();
5610
5611            Debug.assert(isLeftHandSideExpression(expression));
5612            if ((token() === SyntaxKind.PlusPlusToken || token() === SyntaxKind.MinusMinusToken) && !scanner.hasPrecedingLineBreak()) {
5613                const operator = token() as PostfixUnaryOperator;
5614                nextToken();
5615                return finishNode(factory.createPostfixUnaryExpression(expression, operator), expression.pos);
5616            }
5617
5618            return expression;
5619        }
5620
5621        function parseLeftHandSideExpressionOrHigher(): LeftHandSideExpression {
5622            // Original Ecma:
5623            // LeftHandSideExpression: See 11.2
5624            //      NewExpression
5625            //      CallExpression
5626            //
5627            // Our simplification:
5628            //
5629            // LeftHandSideExpression: See 11.2
5630            //      MemberExpression
5631            //      CallExpression
5632            //
5633            // See comment in parseMemberExpressionOrHigher on how we replaced NewExpression with
5634            // MemberExpression to make our lives easier.
5635            //
5636            // to best understand the below code, it's important to see how CallExpression expands
5637            // out into its own productions:
5638            //
5639            // CallExpression:
5640            //      MemberExpression Arguments
5641            //      CallExpression Arguments
5642            //      CallExpression[Expression]
5643            //      CallExpression.IdentifierName
5644            //      import (AssignmentExpression)
5645            //      super Arguments
5646            //      super.IdentifierName
5647            //
5648            // Because of the recursion in these calls, we need to bottom out first. There are three
5649            // bottom out states we can run into: 1) We see 'super' which must start either of
5650            // the last two CallExpression productions. 2) We see 'import' which must start import call.
5651            // 3)we have a MemberExpression which either completes the LeftHandSideExpression,
5652            // or starts the beginning of the first four CallExpression productions.
5653            const pos = getNodePos();
5654            let expression: MemberExpression;
5655            if (token() === SyntaxKind.ImportKeyword) {
5656                if (lookAhead(nextTokenIsOpenParenOrLessThan)) {
5657                    // We don't want to eagerly consume all import keyword as import call expression so we look ahead to find "("
5658                    // For example:
5659                    //      var foo3 = require("subfolder
5660                    //      import * as foo1 from "module-from-node
5661                    // We want this import to be a statement rather than import call expression
5662                    sourceFlags |= NodeFlags.PossiblyContainsDynamicImport;
5663                    expression = parseTokenNode<PrimaryExpression>();
5664                }
5665                else if (lookAhead(nextTokenIsDot)) {
5666                    // This is an 'import.*' metaproperty (i.e. 'import.meta')
5667                    nextToken(); // advance past the 'import'
5668                    nextToken(); // advance past the dot
5669                    expression = finishNode(factory.createMetaProperty(SyntaxKind.ImportKeyword, parseIdentifierName()), pos);
5670                    sourceFlags |= NodeFlags.PossiblyContainsImportMeta;
5671                }
5672                else {
5673                    expression = parseMemberExpressionOrHigher();
5674                }
5675            }
5676            else {
5677                expression = token() === SyntaxKind.SuperKeyword ? parseSuperExpression() : parseMemberExpressionOrHigher();
5678            }
5679
5680            // Now, we *may* be complete.  However, we might have consumed the start of a
5681            // CallExpression or OptionalExpression.  As such, we need to consume the rest
5682            // of it here to be complete.
5683            return parseCallExpressionRest(pos, expression);
5684        }
5685
5686        function parseMemberExpressionOrHigher(): MemberExpression {
5687            // Note: to make our lives simpler, we decompose the NewExpression productions and
5688            // place ObjectCreationExpression and FunctionExpression into PrimaryExpression.
5689            // like so:
5690            //
5691            //   PrimaryExpression : See 11.1
5692            //      this
5693            //      Identifier
5694            //      Literal
5695            //      ArrayLiteral
5696            //      ObjectLiteral
5697            //      (Expression)
5698            //      FunctionExpression
5699            //      new MemberExpression Arguments?
5700            //
5701            //   MemberExpression : See 11.2
5702            //      PrimaryExpression
5703            //      MemberExpression[Expression]
5704            //      MemberExpression.IdentifierName
5705            //
5706            //   CallExpression : See 11.2
5707            //      MemberExpression
5708            //      CallExpression Arguments
5709            //      CallExpression[Expression]
5710            //      CallExpression.IdentifierName
5711            //
5712            // Technically this is ambiguous.  i.e. CallExpression defines:
5713            //
5714            //   CallExpression:
5715            //      CallExpression Arguments
5716            //
5717            // If you see: "new Foo()"
5718            //
5719            // Then that could be treated as a single ObjectCreationExpression, or it could be
5720            // treated as the invocation of "new Foo".  We disambiguate that in code (to match
5721            // the original grammar) by making sure that if we see an ObjectCreationExpression
5722            // we always consume arguments if they are there. So we treat "new Foo()" as an
5723            // object creation only, and not at all as an invocation.  Another way to think
5724            // about this is that for every "new" that we see, we will consume an argument list if
5725            // it is there as part of the *associated* object creation node.  Any additional
5726            // argument lists we see, will become invocation expressions.
5727            //
5728            // Because there are no other places in the grammar now that refer to FunctionExpression
5729            // or ObjectCreationExpression, it is safe to push down into the PrimaryExpression
5730            // production.
5731            //
5732            // Because CallExpression and MemberExpression are left recursive, we need to bottom out
5733            // of the recursion immediately.  So we parse out a primary expression to start with.
5734            const pos = getNodePos();
5735            let expression;
5736
5737            if (inEtsExtendComponentsContext() && extendEtsComponentDeclaration && token() === SyntaxKind.DotToken) {
5738                expression = finishVirtualNode(factory.createIdentifier(extendEtsComponentDeclaration.instance, /*typeArguments*/ undefined, SyntaxKind.Identifier), pos, pos);
5739            }
5740            else if (inEtsStylesComponentsContext() && stylesEtsComponentDeclaration && token() === SyntaxKind.DotToken) {
5741                expression = finishVirtualNode(factory.createIdentifier(stylesEtsComponentDeclaration.instance, /*typeArguments*/ undefined, SyntaxKind.Identifier), pos, pos);
5742            }
5743            else if (inEtsStateStylesContext() && stateStylesRootNode && token() === SyntaxKind.DotToken) {
5744                expression = finishVirtualNode(factory.createIdentifier(`${stateStylesRootNode}Instance`, /*typeArguments*/ undefined, SyntaxKind.Identifier), pos, pos);
5745            }
5746            else {
5747                expression = parsePrimaryExpression();
5748            }
5749            return parseMemberExpressionRest(pos, expression, /*allowOptionalChain*/ true);
5750        }
5751
5752        function parseSuperExpression(): MemberExpression {
5753            const pos = getNodePos();
5754            let expression = parseTokenNode<MemberExpression>();
5755            if (token() === SyntaxKind.LessThanToken) {
5756                const startPos = getNodePos();
5757                const typeArguments = tryParse(parseTypeArgumentsInExpression);
5758                if (typeArguments !== undefined) {
5759                    parseErrorAt(startPos, getNodePos(), Diagnostics.super_may_not_use_type_arguments);
5760                    if (!isTemplateStartOfTaggedTemplate()) {
5761                        expression = factory.createExpressionWithTypeArguments(expression, typeArguments);
5762                    }
5763                }
5764            }
5765
5766            if (token() === SyntaxKind.OpenParenToken || token() === SyntaxKind.DotToken || token() === SyntaxKind.OpenBracketToken) {
5767                return expression;
5768            }
5769
5770            // If we have seen "super" it must be followed by '(' or '.'.
5771            // If it wasn't then just try to parse out a '.' and report an error.
5772            parseExpectedToken(SyntaxKind.DotToken, Diagnostics.super_must_be_followed_by_an_argument_list_or_member_access);
5773            // private names will never work with `super` (`super.#foo`), but that's a semantic error, not syntactic
5774            return finishNode(factory.createPropertyAccessExpression(expression, parseRightSideOfDot(/*allowIdentifierNames*/ true, /*allowPrivateIdentifiers*/ true)), pos);
5775        }
5776
5777        function parseJsxElementOrSelfClosingElementOrFragment(inExpressionContext: boolean, topInvalidNodePosition?: number, openingTag?: JsxOpeningElement | JsxOpeningFragment): JsxElement | JsxSelfClosingElement | JsxFragment {
5778            const pos = getNodePos();
5779            const opening = parseJsxOpeningOrSelfClosingElementOrOpeningFragment(inExpressionContext);
5780            let result: JsxElement | JsxSelfClosingElement | JsxFragment;
5781            if (opening.kind === SyntaxKind.JsxOpeningElement) {
5782                let children = parseJsxChildren(opening);
5783                let closingElement: JsxClosingElement;
5784
5785                const lastChild: JsxChild | undefined = children[children.length - 1];
5786                if (lastChild?.kind === SyntaxKind.JsxElement
5787                    && !tagNamesAreEquivalent(lastChild.openingElement.tagName, lastChild.closingElement.tagName)
5788                    && tagNamesAreEquivalent(opening.tagName, lastChild.closingElement.tagName)) {
5789                    // when an unclosed JsxOpeningElement incorrectly parses its parent's JsxClosingElement,
5790                    // restructure (<div>(...<span>...</div>)) --> (<div>(...<span>...</>)</div>)
5791                    // (no need to error; the parent will error)
5792                    const end = lastChild.children.end;
5793                    const newLast = finishNode(factory.createJsxElement(
5794                        lastChild.openingElement,
5795                        lastChild.children,
5796                        finishNode(factory.createJsxClosingElement(finishNode(factory.createIdentifier(""), end, end)), end, end)),
5797                    lastChild.openingElement.pos,
5798                    end);
5799
5800                    children = createNodeArray([...children.slice(0, children.length - 1), newLast], children.pos, end);
5801                    closingElement = lastChild.closingElement;
5802                }
5803                else {
5804                    closingElement = parseJsxClosingElement(opening, inExpressionContext);
5805                    if (!tagNamesAreEquivalent(opening.tagName, closingElement.tagName)) {
5806                        if (openingTag && isJsxOpeningElement(openingTag) && tagNamesAreEquivalent(closingElement.tagName, openingTag.tagName)) {
5807                            // opening incorrectly matched with its parent's closing -- put error on opening
5808                            parseErrorAtRange(opening.tagName, Diagnostics.JSX_element_0_has_no_corresponding_closing_tag, getTextOfNodeFromSourceText(sourceText, opening.tagName));
5809                        }
5810                        else {
5811                            // other opening/closing mismatches -- put error on closing
5812                            parseErrorAtRange(closingElement.tagName, Diagnostics.Expected_corresponding_JSX_closing_tag_for_0, getTextOfNodeFromSourceText(sourceText, opening.tagName));
5813                        }
5814                    }
5815                }
5816                result = finishNode(factory.createJsxElement(opening, children, closingElement), pos);
5817            }
5818            else if (opening.kind === SyntaxKind.JsxOpeningFragment) {
5819                result = finishNode(factory.createJsxFragment(opening, parseJsxChildren(opening), parseJsxClosingFragment(inExpressionContext)), pos);
5820            }
5821            else {
5822                Debug.assert(opening.kind === SyntaxKind.JsxSelfClosingElement);
5823                // Nothing else to do for self-closing elements
5824                result = opening;
5825            }
5826
5827            // If the user writes the invalid code '<div></div><div></div>' in an expression context (i.e. not wrapped in
5828            // an enclosing tag), we'll naively try to parse   ^ this as a 'less than' operator and the remainder of the tag
5829            // as garbage, which will cause the formatter to badly mangle the JSX. Perform a speculative parse of a JSX
5830            // element if we see a < token so that we can wrap it in a synthetic binary expression so the formatter
5831            // does less damage and we can report a better error.
5832            // Since JSX elements are invalid < operands anyway, this lookahead parse will only occur in error scenarios
5833            // of one sort or another.
5834            if (inExpressionContext && token() === SyntaxKind.LessThanToken) {
5835                const topBadPos = typeof topInvalidNodePosition === "undefined" ? result.pos : topInvalidNodePosition;
5836                const invalidElement = tryParse(() => parseJsxElementOrSelfClosingElementOrFragment(/*inExpressionContext*/ true, topBadPos));
5837                if (invalidElement) {
5838                    const operatorToken = createMissingNode(SyntaxKind.CommaToken, /*reportAtCurrentPosition*/ false);
5839                    setTextRangePosWidth(operatorToken, invalidElement.pos, 0);
5840                    parseErrorAt(skipTrivia(sourceText, topBadPos), invalidElement.end, Diagnostics.JSX_expressions_must_have_one_parent_element);
5841                    return finishNode(factory.createBinaryExpression(result, operatorToken as Token<SyntaxKind.CommaToken>, invalidElement), pos) as Node as JsxElement;
5842                }
5843            }
5844
5845            return result;
5846        }
5847
5848        function parseJsxText(): JsxText {
5849            const pos = getNodePos();
5850            const node = factory.createJsxText(scanner.getTokenValue(), currentToken === SyntaxKind.JsxTextAllWhiteSpaces);
5851            currentToken = scanner.scanJsxToken();
5852            return finishNode(node, pos);
5853        }
5854
5855        function parseJsxChild(openingTag: JsxOpeningElement | JsxOpeningFragment, token: JsxTokenSyntaxKind): JsxChild | undefined {
5856            switch (token) {
5857                case SyntaxKind.EndOfFileToken:
5858                    // If we hit EOF, issue the error at the tag that lacks the closing element
5859                    // rather than at the end of the file (which is useless)
5860                    if (isJsxOpeningFragment(openingTag)) {
5861                        parseErrorAtRange(openingTag, Diagnostics.JSX_fragment_has_no_corresponding_closing_tag);
5862                    }
5863                    else {
5864                        // We want the error span to cover only 'Foo.Bar' in < Foo.Bar >
5865                        // or to cover only 'Foo' in < Foo >
5866                        const tag = openingTag.tagName;
5867                        const start = skipTrivia(sourceText, tag.pos);
5868                        parseErrorAt(start, tag.end, Diagnostics.JSX_element_0_has_no_corresponding_closing_tag, getTextOfNodeFromSourceText(sourceText, openingTag.tagName));
5869                    }
5870                    return undefined;
5871                case SyntaxKind.LessThanSlashToken:
5872                case SyntaxKind.ConflictMarkerTrivia:
5873                    return undefined;
5874                case SyntaxKind.JsxText:
5875                case SyntaxKind.JsxTextAllWhiteSpaces:
5876                    return parseJsxText();
5877                case SyntaxKind.OpenBraceToken:
5878                    return parseJsxExpression(/*inExpressionContext*/ false);
5879                case SyntaxKind.LessThanToken:
5880                    return parseJsxElementOrSelfClosingElementOrFragment(/*inExpressionContext*/ false, /*topInvalidNodePosition*/ undefined, openingTag);
5881                default:
5882                    return Debug.assertNever(token);
5883            }
5884        }
5885
5886        function parseJsxChildren(openingTag: JsxOpeningElement | JsxOpeningFragment): NodeArray<JsxChild> {
5887            const list = [];
5888            const listPos = getNodePos();
5889            const saveParsingContext = parsingContext;
5890            parsingContext |= 1 << ParsingContext.JsxChildren;
5891
5892            while (true) {
5893                const child = parseJsxChild(openingTag, currentToken = scanner.reScanJsxToken());
5894                if (!child) break;
5895                list.push(child);
5896                if (isJsxOpeningElement(openingTag)
5897                    && child?.kind === SyntaxKind.JsxElement
5898                    && !tagNamesAreEquivalent(child.openingElement.tagName, child.closingElement.tagName)
5899                    && tagNamesAreEquivalent(openingTag.tagName, child.closingElement.tagName)) {
5900                    // stop after parsing a mismatched child like <div>...(<span></div>) in order to reattach the </div> higher
5901                    break;
5902                }
5903            }
5904
5905            parsingContext = saveParsingContext;
5906            return createNodeArray(list, listPos);
5907        }
5908
5909        function parseJsxAttributes(): JsxAttributes {
5910            const pos = getNodePos();
5911            return finishNode(factory.createJsxAttributes(parseList(ParsingContext.JsxAttributes, parseJsxAttribute)), pos);
5912        }
5913
5914        function parseJsxOpeningOrSelfClosingElementOrOpeningFragment(inExpressionContext: boolean): JsxOpeningElement | JsxSelfClosingElement | JsxOpeningFragment {
5915            const pos = getNodePos();
5916
5917            parseExpected(SyntaxKind.LessThanToken);
5918
5919            if (token() === SyntaxKind.GreaterThanToken) {
5920                // See below for explanation of scanJsxText
5921                scanJsxText();
5922                return finishNode(factory.createJsxOpeningFragment(), pos);
5923            }
5924            const tagName = parseJsxElementName();
5925            const typeArguments = (contextFlags & NodeFlags.JavaScriptFile) === 0 ? tryParseTypeArguments() : undefined;
5926            const attributes = parseJsxAttributes();
5927
5928            let node: JsxOpeningLikeElement;
5929
5930            if (token() === SyntaxKind.GreaterThanToken) {
5931                // Closing tag, so scan the immediately-following text with the JSX scanning instead
5932                // of regular scanning to avoid treating illegal characters (e.g. '#') as immediate
5933                // scanning errors
5934                scanJsxText();
5935                node = factory.createJsxOpeningElement(tagName, typeArguments, attributes);
5936            }
5937            else {
5938                parseExpected(SyntaxKind.SlashToken);
5939                if (parseExpected(SyntaxKind.GreaterThanToken, /*diagnostic*/ undefined, /*shouldAdvance*/ false)) {
5940                    // manually advance the scanner in order to look for jsx text inside jsx
5941                    if (inExpressionContext) {
5942                        nextToken();
5943                    }
5944                    else {
5945                        scanJsxText();
5946                    }
5947                }
5948                node = factory.createJsxSelfClosingElement(tagName, typeArguments, attributes);
5949            }
5950
5951            return finishNode(node, pos);
5952        }
5953
5954        function parseJsxElementName(): JsxTagNameExpression {
5955            const pos = getNodePos();
5956            scanJsxIdentifier();
5957            // JsxElement can have name in the form of
5958            //      propertyAccessExpression
5959            //      primaryExpression in the form of an identifier and "this" keyword
5960            // We can't just simply use parseLeftHandSideExpressionOrHigher because then we will start consider class,function etc as a keyword
5961            // We only want to consider "this" as a primaryExpression
5962            let expression: JsxTagNameExpression = token() === SyntaxKind.ThisKeyword ?
5963                parseTokenNode<ThisExpression>() : parseIdentifierName();
5964            while (parseOptional(SyntaxKind.DotToken)) {
5965                expression = finishNode(factory.createPropertyAccessExpression(expression, parseRightSideOfDot(/*allowIdentifierNames*/ true, /*allowPrivateIdentifiers*/ false)), pos) as JsxTagNamePropertyAccess;
5966            }
5967            return expression;
5968        }
5969
5970        function parseJsxExpression(inExpressionContext: boolean): JsxExpression | undefined {
5971            const pos = getNodePos();
5972            if (!parseExpected(SyntaxKind.OpenBraceToken)) {
5973                return undefined;
5974            }
5975
5976            let dotDotDotToken: DotDotDotToken | undefined;
5977            let expression: Expression | undefined;
5978            if (token() !== SyntaxKind.CloseBraceToken) {
5979                dotDotDotToken = parseOptionalToken(SyntaxKind.DotDotDotToken);
5980                // Only an AssignmentExpression is valid here per the JSX spec,
5981                // but we can unambiguously parse a comma sequence and provide
5982                // a better error message in grammar checking.
5983                expression = parseExpression();
5984            }
5985            if (inExpressionContext) {
5986                parseExpected(SyntaxKind.CloseBraceToken);
5987            }
5988            else {
5989                if (parseExpected(SyntaxKind.CloseBraceToken, /*message*/ undefined, /*shouldAdvance*/ false)) {
5990                    scanJsxText();
5991                }
5992            }
5993
5994            return finishNode(factory.createJsxExpression(dotDotDotToken, expression), pos);
5995        }
5996
5997        function parseJsxAttribute(): JsxAttribute | JsxSpreadAttribute {
5998            if (token() === SyntaxKind.OpenBraceToken) {
5999                return parseJsxSpreadAttribute();
6000            }
6001
6002            scanJsxIdentifier();
6003            const pos = getNodePos();
6004            return finishNode(factory.createJsxAttribute(parseIdentifierName(), parseJsxAttributeValue()), pos);
6005        }
6006
6007        function parseJsxAttributeValue(): JsxAttributeValue | undefined {
6008            if (token() === SyntaxKind.EqualsToken) {
6009                if (scanJsxAttributeValue() === SyntaxKind.StringLiteral) {
6010                    return parseLiteralNode() as StringLiteral;
6011                }
6012                if (token() === SyntaxKind.OpenBraceToken) {
6013                    return parseJsxExpression(/*inExpressionContext*/ true);
6014                }
6015                if (token() === SyntaxKind.LessThanToken) {
6016                    return parseJsxElementOrSelfClosingElementOrFragment(/*inExpressionContext*/ true);
6017                }
6018                parseErrorAtCurrentToken(Diagnostics.or_JSX_element_expected);
6019            }
6020            return undefined;
6021        }
6022
6023        function parseJsxSpreadAttribute(): JsxSpreadAttribute {
6024            const pos = getNodePos();
6025            parseExpected(SyntaxKind.OpenBraceToken);
6026            parseExpected(SyntaxKind.DotDotDotToken);
6027            const expression = parseExpression();
6028            parseExpected(SyntaxKind.CloseBraceToken);
6029            return finishNode(factory.createJsxSpreadAttribute(expression), pos);
6030        }
6031
6032        function parseJsxClosingElement(open: JsxOpeningElement, inExpressionContext: boolean): JsxClosingElement {
6033            const pos = getNodePos();
6034            parseExpected(SyntaxKind.LessThanSlashToken);
6035            const tagName = parseJsxElementName();
6036            if (parseExpected(SyntaxKind.GreaterThanToken, /*diagnostic*/ undefined, /*shouldAdvance*/ false)) {
6037                // manually advance the scanner in order to look for jsx text inside jsx
6038                if (inExpressionContext || !tagNamesAreEquivalent(open.tagName, tagName)) {
6039                    nextToken();
6040                }
6041                else {
6042                    scanJsxText();
6043                }
6044            }
6045            return finishNode(factory.createJsxClosingElement(tagName), pos);
6046        }
6047
6048        function parseJsxClosingFragment(inExpressionContext: boolean): JsxClosingFragment {
6049            const pos = getNodePos();
6050            parseExpected(SyntaxKind.LessThanSlashToken);
6051            if (tokenIsIdentifierOrKeyword(token())) {
6052                parseErrorAtRange(parseJsxElementName(), Diagnostics.Expected_corresponding_closing_tag_for_JSX_fragment);
6053            }
6054            if (parseExpected(SyntaxKind.GreaterThanToken, /*diagnostic*/ undefined, /*shouldAdvance*/ false)) {
6055                // manually advance the scanner in order to look for jsx text inside jsx
6056                if (inExpressionContext) {
6057                    nextToken();
6058                }
6059                else {
6060                    scanJsxText();
6061                }
6062            }
6063            return finishNode(factory.createJsxJsxClosingFragment(), pos);
6064        }
6065
6066        function parseTypeAssertion(): TypeAssertion {
6067            const pos = getNodePos();
6068            parseExpected(SyntaxKind.LessThanToken);
6069            const type = parseType();
6070            parseExpected(SyntaxKind.GreaterThanToken);
6071            const expression = parseSimpleUnaryExpression();
6072            return finishNode(factory.createTypeAssertion(type, expression), pos);
6073        }
6074
6075        function nextTokenIsIdentifierOrKeywordOrOpenBracketOrTemplate() {
6076            nextToken();
6077            return tokenIsIdentifierOrKeyword(token())
6078                || token() === SyntaxKind.OpenBracketToken
6079                || isTemplateStartOfTaggedTemplate();
6080        }
6081
6082        function isStartOfOptionalPropertyOrElementAccessChain() {
6083            return token() === SyntaxKind.QuestionDotToken
6084                && lookAhead(nextTokenIsIdentifierOrKeywordOrOpenBracketOrTemplate);
6085        }
6086
6087        function tryReparseOptionalChain(node: Expression) {
6088            if (node.flags & NodeFlags.OptionalChain) {
6089                return true;
6090            }
6091            // check for an optional chain in a non-null expression
6092            if (isNonNullExpression(node)) {
6093                let expr = node.expression;
6094                while (isNonNullExpression(expr) && !(expr.flags & NodeFlags.OptionalChain)) {
6095                    expr = expr.expression;
6096                }
6097                if (expr.flags & NodeFlags.OptionalChain) {
6098                    // this is part of an optional chain. Walk down from `node` to `expression` and set the flag.
6099                    while (isNonNullExpression(node)) {
6100                        (node as Mutable<NonNullExpression>).flags |= NodeFlags.OptionalChain;
6101                        node = node.expression;
6102                    }
6103                    return true;
6104                }
6105            }
6106            return false;
6107        }
6108
6109        function parsePropertyAccessExpressionRest(pos: number, expression: LeftHandSideExpression, questionDotToken: QuestionDotToken | undefined) {
6110            const name = parseRightSideOfDot(/*allowIdentifierNames*/ true, /*allowPrivateIdentifiers*/ true);
6111            const isOptionalChain = questionDotToken || tryReparseOptionalChain(expression);
6112            const propertyAccess = isOptionalChain ?
6113                factory.createPropertyAccessChain(expression, questionDotToken, name) :
6114                factory.createPropertyAccessExpression(expression, name);
6115            if (isOptionalChain && isPrivateIdentifier(propertyAccess.name)) {
6116                parseErrorAtRange(propertyAccess.name, Diagnostics.An_optional_chain_cannot_contain_private_identifiers);
6117            }
6118            if (isExpressionWithTypeArguments(expression) && expression.typeArguments) {
6119                const pos = expression.typeArguments.pos - 1;
6120                const end = skipTrivia(sourceText, expression.typeArguments.end) + 1;
6121                parseErrorAt(pos, end, Diagnostics.An_instantiation_expression_cannot_be_followed_by_a_property_access);
6122            }
6123            return finishNode(propertyAccess, pos);
6124        }
6125
6126        function parseElementAccessExpressionRest(pos: number, expression: LeftHandSideExpression, questionDotToken: QuestionDotToken | undefined) {
6127            let argumentExpression: Expression;
6128            if (token() === SyntaxKind.CloseBracketToken) {
6129                argumentExpression = createMissingNode(SyntaxKind.Identifier, /*reportAtCurrentPosition*/ true, Diagnostics.An_element_access_expression_should_take_an_argument);
6130            }
6131            else {
6132                const argument = allowInAnd(parseExpression);
6133                if (isStringOrNumericLiteralLike(argument)) {
6134                    argument.text = internIdentifier(argument.text);
6135                }
6136                argumentExpression = argument;
6137            }
6138
6139            parseExpected(SyntaxKind.CloseBracketToken);
6140
6141            const indexedAccess = questionDotToken || tryReparseOptionalChain(expression) ?
6142                factory.createElementAccessChain(expression, questionDotToken, argumentExpression) :
6143                factory.createElementAccessExpression(expression, argumentExpression);
6144            return finishNode(indexedAccess, pos);
6145        }
6146
6147        function parseMemberExpressionRest(pos: number, expression: LeftHandSideExpression, allowOptionalChain: boolean): MemberExpression {
6148            while (true) {
6149                let questionDotToken: QuestionDotToken | undefined;
6150                let isPropertyAccess = false;
6151                if (allowOptionalChain && isStartOfOptionalPropertyOrElementAccessChain()) {
6152                    questionDotToken = parseExpectedToken(SyntaxKind.QuestionDotToken);
6153                    isPropertyAccess = tokenIsIdentifierOrKeyword(token());
6154                }
6155                else {
6156                    isPropertyAccess = parseOptional(SyntaxKind.DotToken);
6157                }
6158
6159                if (isPropertyAccess) {
6160                    expression = parsePropertyAccessExpressionRest(pos, expression, questionDotToken);
6161                    continue;
6162                }
6163
6164                // when in the [Decorator] context, we do not parse ElementAccess as it could be part of a ComputedPropertyName
6165                if ((questionDotToken || !inDecoratorContext()) && parseOptional(SyntaxKind.OpenBracketToken)) {
6166                    expression = parseElementAccessExpressionRest(pos, expression, questionDotToken);
6167                    continue;
6168                }
6169
6170                if (isTemplateStartOfTaggedTemplate()) {
6171                    // Absorb type arguments into TemplateExpression when preceding expression is ExpressionWithTypeArguments
6172                    expression = !questionDotToken && expression.kind === SyntaxKind.ExpressionWithTypeArguments ?
6173                        parseTaggedTemplateRest(pos, (expression as ExpressionWithTypeArguments).expression, questionDotToken, (expression as ExpressionWithTypeArguments).typeArguments) :
6174                        parseTaggedTemplateRest(pos, expression, questionDotToken, /*typeArguments*/ undefined);
6175                    continue;
6176                }
6177
6178                if (!questionDotToken) {
6179                    if (token() === SyntaxKind.ExclamationToken && !scanner.hasPrecedingLineBreak()) {
6180                        nextToken();
6181                        expression = finishNode(factory.createNonNullExpression(expression), pos);
6182                        continue;
6183                    }
6184                    const typeArguments = tryParse(parseTypeArgumentsInExpression);
6185                    if (typeArguments) {
6186                        expression = finishNode(factory.createExpressionWithTypeArguments(expression, typeArguments), pos);
6187                        continue;
6188                    }
6189                }
6190
6191                return expression as MemberExpression;
6192            }
6193        }
6194
6195        function isTemplateStartOfTaggedTemplate() {
6196            return token() === SyntaxKind.NoSubstitutionTemplateLiteral || token() === SyntaxKind.TemplateHead;
6197        }
6198
6199        function parseTaggedTemplateRest(pos: number, tag: LeftHandSideExpression, questionDotToken: QuestionDotToken | undefined, typeArguments: NodeArray<TypeNode> | undefined) {
6200            const tagExpression = factory.createTaggedTemplateExpression(
6201                tag,
6202                typeArguments,
6203                token() === SyntaxKind.NoSubstitutionTemplateLiteral ?
6204                    (reScanTemplateHeadOrNoSubstitutionTemplate(), parseLiteralNode() as NoSubstitutionTemplateLiteral) :
6205                    parseTemplateExpression(/*isTaggedTemplate*/ true)
6206            );
6207            if (questionDotToken || tag.flags & NodeFlags.OptionalChain) {
6208                (tagExpression as Mutable<Node>).flags |= NodeFlags.OptionalChain;
6209            }
6210            tagExpression.questionDotToken = questionDotToken;
6211            return finishNode(tagExpression, pos);
6212        }
6213
6214        function parseCallExpressionRest(pos: number, expression: LeftHandSideExpression): LeftHandSideExpression {
6215            let currentNodeName: string | undefined;
6216            while (true) {
6217                expression = parseMemberExpressionRest(pos, expression, /*allowOptionalChain*/ true);
6218                let typeArguments: NodeArray<TypeNode> | undefined;
6219                const questionDotToken = parseOptionalToken(SyntaxKind.QuestionDotToken);
6220                if (questionDotToken) {
6221                    typeArguments = tryParse(parseTypeArgumentsInExpression);
6222                    if (isTemplateStartOfTaggedTemplate()) {
6223                        expression = parseTaggedTemplateRest(pos, expression, questionDotToken, typeArguments);
6224                        continue;
6225                    }
6226                }
6227                if (typeArguments || token() === SyntaxKind.OpenParenToken) {
6228                    // Absorb type arguments into CallExpression when preceding expression is ExpressionWithTypeArguments
6229                    if (!questionDotToken && expression.kind === SyntaxKind.ExpressionWithTypeArguments) {
6230                        typeArguments = (expression as ExpressionWithTypeArguments).typeArguments;
6231                        expression = (expression as ExpressionWithTypeArguments).expression;
6232                    }
6233
6234                    if (isValidVirtualTypeArgumentsContext() && isPropertyAccessExpression(expression)) {
6235                        const [rootNode, type] = getRootComponent(expression, sourceFileCompilerOptions);
6236                        if (rootNode && type) {
6237                            let rootNodeName = '';
6238                            if (type === 'otherType') {
6239                                rootNodeName = 'Common';
6240                            } else {
6241                                rootNodeName = (<Identifier>(rootNode.expression)).escapedText.toString();
6242                            }
6243                            currentNodeName = getTextOfPropertyName(expression.name).toString();
6244                            if (currentNodeName === sourceFileCompilerOptions?.ets?.styles?.property) {
6245                                setEtsStateStylesContext(true);
6246                                stateStylesRootNode = rootNodeName;
6247                            }
6248                            else {
6249                                setEtsStateStylesContext(false);
6250                                stateStylesRootNode = undefined;
6251                            }
6252                            const syntaxComponents = sourceFileCompilerOptions?.ets?.syntaxComponents?.attrUICallback?.filter(
6253                                (item: any) => item.name === rootNodeName);
6254                            if (type === 'callExpressionComponentType' && syntaxComponents && syntaxComponents.length &&
6255                                syntaxComponents[0]?.attributes?.includes(currentNodeName)) {
6256                                setSyntaxComponentContext(true);
6257                            } else if (type === 'etsComponentType') {
6258                                typeArguments = parseEtsTypeArguments(pos, `${rootNodeName}Attribute`);
6259                            }
6260                        }
6261                        else if (inEtsStateStylesContext() && stateStylesRootNode) {
6262                            typeArguments = parseEtsTypeArguments(pos, `${stateStylesRootNode}Attribute`);
6263                        } else if (inEtsStylesComponentsContext() || inEtsExtendComponentsContext()) {
6264                            const virtualNode = getVirtualEtsComponent(expression);
6265                            if (virtualNode) {
6266                                let rootNodeName = (<Identifier>(virtualNode.expression)).escapedText.toString();
6267                                currentNodeName = getTextOfPropertyName(expression.name).toString();
6268                                if (currentNodeName === sourceFileCompilerOptions?.ets?.styles?.property) {
6269                                    setEtsStateStylesContext(true);
6270                                    rootNodeName = rootNodeName.replace("Instance", "");
6271                                    stateStylesRootNode = rootNodeName;
6272                                    typeArguments = parseEtsTypeArguments(pos, `${rootNodeName}Attribute`);
6273                                }
6274                            }
6275                        }
6276                    }
6277                    if (isValidVirtualTypeArgumentsContext() && ts.isIdentifier(expression) &&
6278                        sourceFileCompilerOptions?.ets?.syntaxComponents?.paramsUICallback?.includes(expression.escapedText.toString())) {
6279                        setSyntaxComponentContext(true);
6280                    }
6281                    const argumentList = parseArgumentList();
6282                    const callExpr = questionDotToken || tryReparseOptionalChain(expression) ?
6283                        factory.createCallChain(expression, questionDotToken, typeArguments, argumentList) :
6284                        factory.createCallExpression(expression, typeArguments, argumentList);
6285                    expression = finishNode(callExpr, pos);
6286                    continue;
6287                }
6288                if (questionDotToken) {
6289                    // We parsed `?.` but then failed to parse anything, so report a missing identifier here.
6290                    const name = createMissingNode<Identifier>(SyntaxKind.Identifier, /*reportAtCurrentPosition*/ false, Diagnostics.Identifier_expected);
6291                    expression = finishNode(factory.createPropertyAccessChain(expression, questionDotToken, name), pos);
6292                }
6293                break;
6294            }
6295            if (currentNodeName === sourceFileCompilerOptions?.ets?.styles?.property) {
6296                setEtsStateStylesContext(false);
6297                stateStylesRootNode = undefined;
6298            }
6299            return expression;
6300        }
6301
6302        function isValidVirtualTypeArgumentsContext(): boolean {
6303            return inBuildContext() || inBuilderContext() || inEtsStylesComponentsContext() || inEtsExtendComponentsContext();
6304        }
6305
6306        function parseArgumentList() {
6307            parseExpected(SyntaxKind.OpenParenToken);
6308            const result = parseDelimitedList(ParsingContext.ArgumentExpressions, parseArgumentExpression);
6309            parseExpected(SyntaxKind.CloseParenToken);
6310            return result;
6311        }
6312
6313        function parseTypeArgumentsInExpression() {
6314            if ((contextFlags & NodeFlags.JavaScriptFile) !== 0) {
6315                // TypeArguments must not be parsed in JavaScript files to avoid ambiguity with binary operators.
6316                return undefined;
6317            }
6318
6319            if (reScanLessThanToken() !== SyntaxKind.LessThanToken) {
6320                return undefined;
6321            }
6322            nextToken();
6323
6324            const typeArguments = parseDelimitedList(ParsingContext.TypeArguments, parseType);
6325            if (reScanGreaterToken() !== SyntaxKind.GreaterThanToken) {
6326                // If it doesn't have the closing `>` then it's definitely not an type argument list.
6327                return undefined;
6328            }
6329            nextToken();
6330
6331            // We successfully parsed a type argument list. The next token determines whether we want to
6332            // treat it as such. If the type argument list is followed by `(` or a template literal, as in
6333            // `f<number>(42)`, we favor the type argument interpretation even though JavaScript would view
6334            // it as a relational expression.
6335            return typeArguments && canFollowTypeArgumentsInExpression() ? typeArguments : undefined;
6336        }
6337
6338        function canFollowTypeArgumentsInExpression(): boolean {
6339            switch (token()) {
6340                // These tokens can follow a type argument list in a call expression.
6341                case SyntaxKind.OpenParenToken:                 // foo<x>(
6342                case SyntaxKind.NoSubstitutionTemplateLiteral:  // foo<T> `...`
6343                case SyntaxKind.TemplateHead:                   // foo<T> `...${100}...`
6344                    return true;
6345                // A type argument list followed by `<` never makes sense, and a type argument list followed
6346                // by `>` is ambiguous with a (re-scanned) `>>` operator, so we disqualify both. Also, in
6347                // this context, `+` and `-` are unary operators, not binary operators.
6348                case SyntaxKind.LessThanToken:
6349                case SyntaxKind.GreaterThanToken:
6350                case SyntaxKind.PlusToken:
6351                case SyntaxKind.MinusToken:
6352                    return false;
6353            }
6354            // We favor the type argument list interpretation when it is immediately followed by
6355            // a line break, a binary operator, or something that can't start an expression.
6356            return scanner.hasPrecedingLineBreak() || isBinaryOperator() || !isStartOfExpression();
6357        }
6358
6359        function isCurrentTokenAnEtsComponentExpression(): boolean {
6360            if (!inEtsComponentsContext()) {
6361                return false;
6362            }
6363            const components = sourceFileCompilerOptions.ets?.components ?? [];
6364            return components.includes(scanner.getTokenText());
6365        }
6366
6367        function parseEtsComponentExpression(): EtsComponentExpression {
6368            const pos = getNodePos();
6369            const name = parseBindingIdentifier();
6370            const argumentList = parseArgumentList();
6371            const body = token() === SyntaxKind.OpenBraceToken ? parseFunctionBlock(SignatureFlags.None) : undefined;
6372            const node = factory.createEtsComponentExpression(name, argumentList, body);
6373            return finishNode(node, pos);
6374        }
6375
6376        function parsePrimaryExpression(): PrimaryExpression {
6377            switch (token()) {
6378                case SyntaxKind.NumericLiteral:
6379                case SyntaxKind.BigIntLiteral:
6380                case SyntaxKind.StringLiteral:
6381                case SyntaxKind.NoSubstitutionTemplateLiteral:
6382                    return parseLiteralNode();
6383                case SyntaxKind.ThisKeyword:
6384                case SyntaxKind.SuperKeyword:
6385                case SyntaxKind.NullKeyword:
6386                case SyntaxKind.TrueKeyword:
6387                case SyntaxKind.FalseKeyword:
6388                    return parseTokenNode<PrimaryExpression>();
6389                case SyntaxKind.OpenParenToken:
6390                    return parseParenthesizedExpression();
6391                case SyntaxKind.OpenBracketToken:
6392                    return parseArrayLiteralExpression();
6393                case SyntaxKind.OpenBraceToken:
6394                    return parseObjectLiteralExpression();
6395                case SyntaxKind.AsyncKeyword:
6396                    // Async arrow functions are parsed earlier in parseAssignmentExpressionOrHigher.
6397                    // If we encounter `async [no LineTerminator here] function` then this is an async
6398                    // function; otherwise, its an identifier.
6399                    if (!lookAhead(nextTokenIsFunctionKeywordOnSameLine)) {
6400                        break;
6401                    }
6402
6403                    return parseFunctionExpression();
6404                case SyntaxKind.ClassKeyword:
6405                    return parseClassExpression();
6406                case SyntaxKind.FunctionKeyword:
6407                    return parseFunctionExpression();
6408                case SyntaxKind.NewKeyword:
6409                    return parseNewExpressionOrNewDotTarget();
6410                case SyntaxKind.SlashToken:
6411                case SyntaxKind.SlashEqualsToken:
6412                    if (reScanSlashToken() === SyntaxKind.RegularExpressionLiteral) {
6413                        return parseLiteralNode();
6414                    }
6415                    break;
6416                case SyntaxKind.TemplateHead:
6417                    return parseTemplateExpression(/* isTaggedTemplate */ false);
6418                case SyntaxKind.PrivateIdentifier:
6419                    return parsePrivateIdentifier();
6420            }
6421
6422            if(isCurrentTokenAnEtsComponentExpression() && !inEtsNewExpressionContext()){
6423                return parseEtsComponentExpression();
6424            }
6425
6426            return parseIdentifier(Diagnostics.Expression_expected);
6427        }
6428
6429        function parseParenthesizedExpression(): ParenthesizedExpression {
6430            const pos = getNodePos();
6431            const hasJSDoc = hasPrecedingJSDocComment();
6432            parseExpected(SyntaxKind.OpenParenToken);
6433            const expression = allowInAnd(parseExpression);
6434            parseExpected(SyntaxKind.CloseParenToken);
6435            return withJSDoc(finishNode(factory.createParenthesizedExpression(expression), pos), hasJSDoc);
6436        }
6437
6438        function parseSpreadElement(): Expression {
6439            const pos = getNodePos();
6440            parseExpected(SyntaxKind.DotDotDotToken);
6441            const expression = parseAssignmentExpressionOrHigher(/*allowReturnTypeInArrowFunction*/ true);
6442            return finishNode(factory.createSpreadElement(expression), pos);
6443        }
6444
6445        function parseArgumentOrArrayLiteralElement(): Expression {
6446            return token() === SyntaxKind.DotDotDotToken ? parseSpreadElement() :
6447                token() === SyntaxKind.CommaToken ? finishNode(factory.createOmittedExpression(), getNodePos()) :
6448                parseAssignmentExpressionOrHigher(/*allowReturnTypeInArrowFunction*/ true);
6449        }
6450
6451        function parseArgumentExpression(): Expression {
6452            return doOutsideOfContext(disallowInAndDecoratorContext, parseArgumentOrArrayLiteralElement);
6453        }
6454
6455        function parseArrayLiteralExpression(): ArrayLiteralExpression {
6456            const pos = getNodePos();
6457            const openBracketPosition = scanner.getTokenPos();
6458            const openBracketParsed = parseExpected(SyntaxKind.OpenBracketToken);
6459            const multiLine = scanner.hasPrecedingLineBreak();
6460            const elements = parseDelimitedList(ParsingContext.ArrayLiteralMembers, parseArgumentOrArrayLiteralElement);
6461            parseExpectedMatchingBrackets(SyntaxKind.OpenBracketToken, SyntaxKind.CloseBracketToken, openBracketParsed, openBracketPosition);
6462            return finishNode(factory.createArrayLiteralExpression(elements, multiLine), pos);
6463        }
6464
6465        function parseObjectLiteralElement(): ObjectLiteralElementLike {
6466            const pos = getNodePos();
6467            const hasJSDoc = hasPrecedingJSDocComment();
6468
6469            if (parseOptionalToken(SyntaxKind.DotDotDotToken)) {
6470                const expression = parseAssignmentExpressionOrHigher(/*allowReturnTypeInArrowFunction*/ true);
6471                return withJSDoc(finishNode(factory.createSpreadAssignment(expression), pos), hasJSDoc);
6472            }
6473
6474            const decorators = parseDecorators();
6475            const modifiers = parseModifiers();
6476
6477            if (parseContextualModifier(SyntaxKind.GetKeyword)) {
6478                return parseAccessorDeclaration(pos, hasJSDoc, decorators, modifiers, SyntaxKind.GetAccessor, SignatureFlags.None);
6479            }
6480            if (parseContextualModifier(SyntaxKind.SetKeyword)) {
6481                return parseAccessorDeclaration(pos, hasJSDoc, decorators, modifiers, SyntaxKind.SetAccessor, SignatureFlags.None);
6482            }
6483
6484            const asteriskToken = parseOptionalToken(SyntaxKind.AsteriskToken);
6485            const tokenIsIdentifier = isIdentifier();
6486            const name = parsePropertyName();
6487
6488            // Disallowing of optional property assignments and definite assignment assertion happens in the grammar checker.
6489            const questionToken = parseOptionalToken(SyntaxKind.QuestionToken);
6490            const exclamationToken = parseOptionalToken(SyntaxKind.ExclamationToken);
6491
6492            if (asteriskToken || token() === SyntaxKind.OpenParenToken || token() === SyntaxKind.LessThanToken) {
6493                return parseMethodDeclaration(pos, hasJSDoc, decorators, modifiers, asteriskToken, name, questionToken, exclamationToken);
6494            }
6495
6496            // check if it is short-hand property assignment or normal property assignment
6497            // NOTE: if token is EqualsToken it is interpreted as CoverInitializedName production
6498            // CoverInitializedName[Yield] :
6499            //     IdentifierReference[?Yield] Initializer[In, ?Yield]
6500            // this is necessary because ObjectLiteral productions are also used to cover grammar for ObjectAssignmentPattern
6501            let node: Mutable<ShorthandPropertyAssignment | PropertyAssignment>;
6502            const isShorthandPropertyAssignment = tokenIsIdentifier && (token() !== SyntaxKind.ColonToken);
6503            if (isShorthandPropertyAssignment) {
6504                const equalsToken = parseOptionalToken(SyntaxKind.EqualsToken);
6505                const objectAssignmentInitializer = equalsToken ? allowInAnd(() => parseAssignmentExpressionOrHigher(/*allowReturnTypeInArrowFunction*/ true)) : undefined;
6506                node = factory.createShorthandPropertyAssignment(name as Identifier, objectAssignmentInitializer);
6507                // Save equals token for error reporting.
6508                // TODO(rbuckton): Consider manufacturing this when we need to report an error as it is otherwise not useful.
6509                node.equalsToken = equalsToken;
6510            }
6511            else {
6512                parseExpected(SyntaxKind.ColonToken);
6513                const initializer = allowInAnd(() => parseAssignmentExpressionOrHigher(/*allowReturnTypeInArrowFunction*/ true));
6514                node = factory.createPropertyAssignment(name, initializer);
6515            }
6516            // Decorators, Modifiers, questionToken, and exclamationToken are not supported by property assignments and are reported in the grammar checker
6517            node.illegalDecorators = decorators;
6518            node.modifiers = modifiers;
6519            node.questionToken = questionToken;
6520            node.exclamationToken = exclamationToken;
6521            return withJSDoc(finishNode(node, pos), hasJSDoc);
6522        }
6523
6524        function parseObjectLiteralExpression(): ObjectLiteralExpression {
6525            const pos = getNodePos();
6526            const openBracePosition = scanner.getTokenPos();
6527            const openBraceParsed = parseExpected(SyntaxKind.OpenBraceToken);
6528            const multiLine = scanner.hasPrecedingLineBreak();
6529            const properties = parseDelimitedList(ParsingContext.ObjectLiteralMembers, parseObjectLiteralElement, /*considerSemicolonAsDelimiter*/ true);
6530            parseExpectedMatchingBrackets(SyntaxKind.OpenBraceToken, SyntaxKind.CloseBraceToken, openBraceParsed, openBracePosition);
6531            return finishNode(factory.createObjectLiteralExpression(properties, multiLine), pos);
6532        }
6533
6534        function parseFunctionExpression(): FunctionExpression {
6535            // GeneratorExpression:
6536            //      function* BindingIdentifier [Yield][opt](FormalParameters[Yield]){ GeneratorBody }
6537            //
6538            // FunctionExpression:
6539            //      function BindingIdentifier[opt](FormalParameters){ FunctionBody }
6540            const savedDecoratorContext = inDecoratorContext();
6541            setDecoratorContext(/*val*/ false);
6542
6543            const pos = getNodePos();
6544            const hasJSDoc = hasPrecedingJSDocComment();
6545            const modifiers = parseModifiers();
6546            parseExpected(SyntaxKind.FunctionKeyword);
6547            const asteriskToken = parseOptionalToken(SyntaxKind.AsteriskToken);
6548            const isGenerator = asteriskToken ? SignatureFlags.Yield : SignatureFlags.None;
6549            const isAsync = some(modifiers, isAsyncModifier) ? SignatureFlags.Await : SignatureFlags.None;
6550            const name = isGenerator && isAsync ? doInYieldAndAwaitContext(parseOptionalBindingIdentifier) :
6551                isGenerator ? doInYieldContext(parseOptionalBindingIdentifier) :
6552                isAsync ? doInAwaitContext(parseOptionalBindingIdentifier) :
6553                parseOptionalBindingIdentifier();
6554
6555            const typeParameters = parseTypeParameters();
6556            const parameters = parseParameters(isGenerator | isAsync);
6557            const type = parseReturnType(SyntaxKind.ColonToken, /*isType*/ false);
6558            const body = parseFunctionBlock(isGenerator | isAsync);
6559
6560            setDecoratorContext(savedDecoratorContext);
6561
6562            const node = factory.createFunctionExpression(modifiers, asteriskToken, name, typeParameters, parameters, type, body);
6563            return withJSDoc(finishNode(node, pos), hasJSDoc);
6564        }
6565
6566        function parseOptionalBindingIdentifier(): Identifier | undefined {
6567            return isBindingIdentifier() ? parseBindingIdentifier() : undefined;
6568        }
6569
6570        function parseNewExpressionOrNewDotTarget(): NewExpression | MetaProperty {
6571            setEtsNewExpressionContext(inEtsComponentsContext());
6572            const pos = getNodePos();
6573            parseExpected(SyntaxKind.NewKeyword);
6574            if (parseOptional(SyntaxKind.DotToken)) {
6575                const name = parseIdentifierName();
6576                return finishNode(factory.createMetaProperty(SyntaxKind.NewKeyword, name), pos);
6577            }
6578            const expressionPos = getNodePos();
6579            let expression: LeftHandSideExpression = parseMemberExpressionRest(expressionPos, parsePrimaryExpression(), /*allowOptionalChain*/ false);
6580            let typeArguments: NodeArray<TypeNode> | undefined;
6581            // Absorb type arguments into NewExpression when preceding expression is ExpressionWithTypeArguments
6582            if (expression.kind === SyntaxKind.ExpressionWithTypeArguments) {
6583                typeArguments = (expression as ExpressionWithTypeArguments).typeArguments;
6584                expression = (expression as ExpressionWithTypeArguments).expression;
6585            }
6586            if (token() === SyntaxKind.QuestionDotToken) {
6587                parseErrorAtCurrentToken(Diagnostics.Invalid_optional_chain_from_new_expression_Did_you_mean_to_call_0, getTextOfNodeFromSourceText(sourceText, expression));
6588            }
6589            const argumentList = token() === SyntaxKind.OpenParenToken ? parseArgumentList() : undefined;
6590            setEtsNewExpressionContext(false);
6591            return finishNode(factory.createNewExpression(expression, typeArguments, argumentList), pos);
6592        }
6593
6594        // STATEMENTS
6595        function parseBlock(ignoreMissingOpenBrace: boolean, diagnosticMessage?: DiagnosticMessage): Block {
6596            const pos = getNodePos();
6597            const hasJSDoc = hasPrecedingJSDocComment();
6598            const openBracePosition = scanner.getTokenPos();
6599            const openBraceParsed = parseExpected(SyntaxKind.OpenBraceToken, diagnosticMessage);
6600            if (openBraceParsed || ignoreMissingOpenBrace) {
6601                const multiLine = scanner.hasPrecedingLineBreak();
6602                const statements = parseList(ParsingContext.BlockStatements, parseStatement);
6603                parseExpectedMatchingBrackets(SyntaxKind.OpenBraceToken, SyntaxKind.CloseBraceToken, openBraceParsed, openBracePosition);
6604                const result = withJSDoc(finishNode(factory.createBlock(statements, multiLine), pos), hasJSDoc);
6605                if (token() === SyntaxKind.EqualsToken) {
6606                    parseErrorAtCurrentToken(Diagnostics.Declaration_or_statement_expected_This_follows_a_block_of_statements_so_if_you_intended_to_write_a_destructuring_assignment_you_might_need_to_wrap_the_the_whole_assignment_in_parentheses);
6607                    nextToken();
6608                }
6609
6610                return result;
6611            }
6612            else {
6613                const statements = createMissingList<Statement>();
6614                return withJSDoc(finishNode(factory.createBlock(statements, /*multiLine*/ undefined), pos), hasJSDoc);
6615            }
6616        }
6617
6618        function parseFunctionBlock(flags: SignatureFlags, diagnosticMessage?: DiagnosticMessage): Block {
6619            const savedYieldContext = inYieldContext();
6620            setYieldContext(!!(flags & SignatureFlags.Yield));
6621
6622            const savedAwaitContext = inAwaitContext();
6623            setAwaitContext(!!(flags & SignatureFlags.Await));
6624
6625            const savedTopLevel = topLevel;
6626            topLevel = false;
6627
6628            // We may be in a [Decorator] context when parsing a function expression or
6629            // arrow function. The body of the function is not in [Decorator] context.
6630            const saveDecoratorContext = inDecoratorContext();
6631            if (saveDecoratorContext) {
6632                setDecoratorContext(/*val*/ false);
6633            }
6634
6635            const block = parseBlock(!!(flags & SignatureFlags.IgnoreMissingOpenBrace), diagnosticMessage);
6636
6637            if (saveDecoratorContext) {
6638                setDecoratorContext(/*val*/ true);
6639            }
6640
6641            topLevel = savedTopLevel;
6642            setYieldContext(savedYieldContext);
6643            setAwaitContext(savedAwaitContext);
6644
6645            return block;
6646        }
6647
6648        function parseEmptyStatement(): Statement {
6649            const pos = getNodePos();
6650            const hasJSDoc = hasPrecedingJSDocComment();
6651            parseExpected(SyntaxKind.SemicolonToken);
6652            return withJSDoc(finishNode(factory.createEmptyStatement(), pos), hasJSDoc);
6653        }
6654
6655        function parseIfStatement(): IfStatement {
6656            const pos = getNodePos();
6657            const hasJSDoc = hasPrecedingJSDocComment();
6658            parseExpected(SyntaxKind.IfKeyword);
6659            const openParenPosition = scanner.getTokenPos();
6660            const openParenParsed = parseExpected(SyntaxKind.OpenParenToken);
6661            const expression = allowInAnd(parseExpression);
6662            parseExpectedMatchingBrackets(SyntaxKind.OpenParenToken, SyntaxKind.CloseParenToken, openParenParsed, openParenPosition);
6663            const thenStatement = parseStatement();
6664            const elseStatement = parseOptional(SyntaxKind.ElseKeyword) ? parseStatement() : undefined;
6665            return withJSDoc(finishNode(factory.createIfStatement(expression, thenStatement, elseStatement), pos), hasJSDoc);
6666        }
6667
6668        function parseDoStatement(): DoStatement {
6669            const pos = getNodePos();
6670            const hasJSDoc = hasPrecedingJSDocComment();
6671            parseExpected(SyntaxKind.DoKeyword);
6672            const statement = parseStatement();
6673            parseExpected(SyntaxKind.WhileKeyword);
6674            const openParenPosition = scanner.getTokenPos();
6675            const openParenParsed = parseExpected(SyntaxKind.OpenParenToken);
6676            const expression = allowInAnd(parseExpression);
6677            parseExpectedMatchingBrackets(SyntaxKind.OpenParenToken, SyntaxKind.CloseParenToken, openParenParsed, openParenPosition);
6678
6679            // From: https://mail.mozilla.org/pipermail/es-discuss/2011-August/016188.html
6680            // 157 min --- All allen at wirfs-brock.com CONF --- "do{;}while(false)false" prohibited in
6681            // spec but allowed in consensus reality. Approved -- this is the de-facto standard whereby
6682            //  do;while(0)x will have a semicolon inserted before x.
6683            parseOptional(SyntaxKind.SemicolonToken);
6684            return withJSDoc(finishNode(factory.createDoStatement(statement, expression), pos), hasJSDoc);
6685        }
6686
6687        function parseWhileStatement(): WhileStatement {
6688            const pos = getNodePos();
6689            const hasJSDoc = hasPrecedingJSDocComment();
6690            parseExpected(SyntaxKind.WhileKeyword);
6691            const openParenPosition = scanner.getTokenPos();
6692            const openParenParsed = parseExpected(SyntaxKind.OpenParenToken);
6693            const expression = allowInAnd(parseExpression);
6694            parseExpectedMatchingBrackets(SyntaxKind.OpenParenToken, SyntaxKind.CloseParenToken, openParenParsed, openParenPosition);
6695            const statement = parseStatement();
6696            return withJSDoc(finishNode(factory.createWhileStatement(expression, statement), pos), hasJSDoc);
6697        }
6698
6699        function parseForOrForInOrForOfStatement(): Statement {
6700            const pos = getNodePos();
6701            const hasJSDoc = hasPrecedingJSDocComment();
6702            parseExpected(SyntaxKind.ForKeyword);
6703            const awaitToken = parseOptionalToken(SyntaxKind.AwaitKeyword);
6704            parseExpected(SyntaxKind.OpenParenToken);
6705
6706            let initializer!: VariableDeclarationList | Expression;
6707            if (token() !== SyntaxKind.SemicolonToken) {
6708                if (token() === SyntaxKind.VarKeyword || token() === SyntaxKind.LetKeyword || token() === SyntaxKind.ConstKeyword) {
6709                    initializer = parseVariableDeclarationList(/*inForStatementInitializer*/ true);
6710                }
6711                else {
6712                    initializer = disallowInAnd(parseExpression);
6713                }
6714            }
6715
6716            let node: IterationStatement;
6717            if (awaitToken ? parseExpected(SyntaxKind.OfKeyword) : parseOptional(SyntaxKind.OfKeyword)) {
6718                const expression = allowInAnd(() => parseAssignmentExpressionOrHigher(/*allowReturnTypeInArrowFunction*/ true));
6719                parseExpected(SyntaxKind.CloseParenToken);
6720                node = factory.createForOfStatement(awaitToken, initializer, expression, parseStatement());
6721            }
6722            else if (parseOptional(SyntaxKind.InKeyword)) {
6723                const expression = allowInAnd(parseExpression);
6724                parseExpected(SyntaxKind.CloseParenToken);
6725                node = factory.createForInStatement(initializer, expression, parseStatement());
6726            }
6727            else {
6728                parseExpected(SyntaxKind.SemicolonToken);
6729                const condition = token() !== SyntaxKind.SemicolonToken && token() !== SyntaxKind.CloseParenToken
6730                    ? allowInAnd(parseExpression)
6731                    : undefined;
6732                parseExpected(SyntaxKind.SemicolonToken);
6733                const incrementor = token() !== SyntaxKind.CloseParenToken
6734                    ? allowInAnd(parseExpression)
6735                    : undefined;
6736                parseExpected(SyntaxKind.CloseParenToken);
6737                node = factory.createForStatement(initializer, condition, incrementor, parseStatement());
6738            }
6739
6740            return withJSDoc(finishNode(node, pos) as ForStatement | ForInOrOfStatement, hasJSDoc);
6741        }
6742
6743        function parseBreakOrContinueStatement(kind: SyntaxKind): BreakOrContinueStatement {
6744            const pos = getNodePos();
6745            const hasJSDoc = hasPrecedingJSDocComment();
6746
6747            parseExpected(kind === SyntaxKind.BreakStatement ? SyntaxKind.BreakKeyword : SyntaxKind.ContinueKeyword);
6748            const label = canParseSemicolon() ? undefined : parseIdentifier();
6749
6750            parseSemicolon();
6751            const node = kind === SyntaxKind.BreakStatement
6752                ? factory.createBreakStatement(label)
6753                : factory.createContinueStatement(label);
6754            return withJSDoc(finishNode(node, pos), hasJSDoc);
6755        }
6756
6757        function parseReturnStatement(): ReturnStatement {
6758            const pos = getNodePos();
6759            const hasJSDoc = hasPrecedingJSDocComment();
6760            parseExpected(SyntaxKind.ReturnKeyword);
6761            const expression = canParseSemicolon() ? undefined : allowInAnd(parseExpression);
6762            parseSemicolon();
6763            return withJSDoc(finishNode(factory.createReturnStatement(expression), pos), hasJSDoc);
6764        }
6765
6766        function parseWithStatement(): WithStatement {
6767            const pos = getNodePos();
6768            const hasJSDoc = hasPrecedingJSDocComment();
6769            parseExpected(SyntaxKind.WithKeyword);
6770            const openParenPosition = scanner.getTokenPos();
6771            const openParenParsed = parseExpected(SyntaxKind.OpenParenToken);
6772            const expression = allowInAnd(parseExpression);
6773            parseExpectedMatchingBrackets(SyntaxKind.OpenParenToken, SyntaxKind.CloseParenToken, openParenParsed, openParenPosition);
6774            const statement = doInsideOfContext(NodeFlags.InWithStatement, parseStatement);
6775            return withJSDoc(finishNode(factory.createWithStatement(expression, statement), pos), hasJSDoc);
6776        }
6777
6778        function parseCaseClause(): CaseClause {
6779            const pos = getNodePos();
6780            const hasJSDoc = hasPrecedingJSDocComment();
6781            parseExpected(SyntaxKind.CaseKeyword);
6782            const expression = allowInAnd(parseExpression);
6783            parseExpected(SyntaxKind.ColonToken);
6784            const statements = parseList(ParsingContext.SwitchClauseStatements, parseStatement);
6785            return withJSDoc(finishNode(factory.createCaseClause(expression, statements), pos), hasJSDoc);
6786        }
6787
6788        function parseDefaultClause(): DefaultClause {
6789            const pos = getNodePos();
6790            parseExpected(SyntaxKind.DefaultKeyword);
6791            parseExpected(SyntaxKind.ColonToken);
6792            const statements = parseList(ParsingContext.SwitchClauseStatements, parseStatement);
6793            return finishNode(factory.createDefaultClause(statements), pos);
6794        }
6795
6796        function parseCaseOrDefaultClause(): CaseOrDefaultClause {
6797            return token() === SyntaxKind.CaseKeyword ? parseCaseClause() : parseDefaultClause();
6798        }
6799
6800        function parseCaseBlock(): CaseBlock {
6801            const pos = getNodePos();
6802            parseExpected(SyntaxKind.OpenBraceToken);
6803            const clauses = parseList(ParsingContext.SwitchClauses, parseCaseOrDefaultClause);
6804            parseExpected(SyntaxKind.CloseBraceToken);
6805            return finishNode(factory.createCaseBlock(clauses), pos);
6806        }
6807
6808        function parseSwitchStatement(): SwitchStatement {
6809            const pos = getNodePos();
6810            const hasJSDoc = hasPrecedingJSDocComment();
6811            parseExpected(SyntaxKind.SwitchKeyword);
6812            parseExpected(SyntaxKind.OpenParenToken);
6813            const expression = allowInAnd(parseExpression);
6814            parseExpected(SyntaxKind.CloseParenToken);
6815            const caseBlock = parseCaseBlock();
6816            return withJSDoc(finishNode(factory.createSwitchStatement(expression, caseBlock), pos), hasJSDoc);
6817        }
6818
6819        function parseThrowStatement(): ThrowStatement {
6820            // ThrowStatement[Yield] :
6821            //      throw [no LineTerminator here]Expression[In, ?Yield];
6822
6823            const pos = getNodePos();
6824            const hasJSDoc = hasPrecedingJSDocComment();
6825            parseExpected(SyntaxKind.ThrowKeyword);
6826
6827            // Because of automatic semicolon insertion, we need to report error if this
6828            // throw could be terminated with a semicolon.  Note: we can't call 'parseExpression'
6829            // directly as that might consume an expression on the following line.
6830            // Instead, we create a "missing" identifier, but don't report an error. The actual error
6831            // will be reported in the grammar walker.
6832            let expression = scanner.hasPrecedingLineBreak() ? undefined : allowInAnd(parseExpression);
6833            if (expression === undefined) {
6834                identifierCount++;
6835                expression = finishNode(factory.createIdentifier(""), getNodePos());
6836            }
6837            if (!tryParseSemicolon()) {
6838                parseErrorForMissingSemicolonAfter(expression);
6839            }
6840            return withJSDoc(finishNode(factory.createThrowStatement(expression), pos), hasJSDoc);
6841        }
6842
6843        // TODO: Review for error recovery
6844        function parseTryStatement(): TryStatement {
6845            const pos = getNodePos();
6846            const hasJSDoc = hasPrecedingJSDocComment();
6847
6848            parseExpected(SyntaxKind.TryKeyword);
6849            const tryBlock = parseBlock(/*ignoreMissingOpenBrace*/ false);
6850            const catchClause = token() === SyntaxKind.CatchKeyword ? parseCatchClause() : undefined;
6851
6852            // If we don't have a catch clause, then we must have a finally clause.  Try to parse
6853            // one out no matter what.
6854            let finallyBlock: Block | undefined;
6855            if (!catchClause || token() === SyntaxKind.FinallyKeyword) {
6856                parseExpected(SyntaxKind.FinallyKeyword, Diagnostics.catch_or_finally_expected);
6857                finallyBlock = parseBlock(/*ignoreMissingOpenBrace*/ false);
6858            }
6859
6860            return withJSDoc(finishNode(factory.createTryStatement(tryBlock, catchClause, finallyBlock), pos), hasJSDoc);
6861        }
6862
6863        function parseCatchClause(): CatchClause {
6864            const pos = getNodePos();
6865            parseExpected(SyntaxKind.CatchKeyword);
6866
6867            let variableDeclaration;
6868            if (parseOptional(SyntaxKind.OpenParenToken)) {
6869                variableDeclaration = parseVariableDeclaration();
6870                parseExpected(SyntaxKind.CloseParenToken);
6871            }
6872            else {
6873                // Keep shape of node to avoid degrading performance.
6874                variableDeclaration = undefined;
6875            }
6876
6877            const block = parseBlock(/*ignoreMissingOpenBrace*/ false);
6878            return finishNode(factory.createCatchClause(variableDeclaration, block), pos);
6879        }
6880
6881        function parseDebuggerStatement(): Statement {
6882            const pos = getNodePos();
6883            const hasJSDoc = hasPrecedingJSDocComment();
6884            parseExpected(SyntaxKind.DebuggerKeyword);
6885            parseSemicolon();
6886            return withJSDoc(finishNode(factory.createDebuggerStatement(), pos), hasJSDoc);
6887        }
6888
6889        function parseExpressionOrLabeledStatement(): ExpressionStatement | LabeledStatement {
6890            // Avoiding having to do the lookahead for a labeled statement by just trying to parse
6891            // out an expression, seeing if it is identifier and then seeing if it is followed by
6892            // a colon.
6893            const pos = getNodePos();
6894            let hasJSDoc = hasPrecedingJSDocComment();
6895            let node: ExpressionStatement | LabeledStatement;
6896            const hasParen = token() === SyntaxKind.OpenParenToken;
6897            const expression = allowInAnd(parseExpression);
6898            if (ts.isIdentifier(expression) && parseOptional(SyntaxKind.ColonToken)) {
6899                node = factory.createLabeledStatement(expression, parseStatement());
6900            }
6901            else {
6902                if (!tryParseSemicolon()) {
6903                    parseErrorForMissingSemicolonAfter(expression);
6904                }
6905                node = factory.createExpressionStatement(expression);
6906                if (hasParen) {
6907                    // do not parse the same jsdoc twice
6908                    hasJSDoc = false;
6909                }
6910            }
6911            return withJSDoc(finishNode(node, pos), hasJSDoc);
6912        }
6913
6914        function nextTokenIsIdentifierOrKeywordOnSameLine() {
6915            nextToken();
6916            return tokenIsIdentifierOrKeyword(token()) && !scanner.hasPrecedingLineBreak();
6917        }
6918
6919        function nextTokenIsClassKeywordOnSameLine() {
6920            nextToken();
6921            return token() === SyntaxKind.ClassKeyword && !scanner.hasPrecedingLineBreak();
6922        }
6923
6924        function nextTokenIsFunctionKeywordOnSameLine() {
6925            nextToken();
6926            return token() === SyntaxKind.FunctionKeyword && !scanner.hasPrecedingLineBreak();
6927        }
6928
6929        function nextTokenIsIdentifierOrKeywordOrLiteralOnSameLine() {
6930            nextToken();
6931            return (tokenIsIdentifierOrKeyword(token()) || token() === SyntaxKind.NumericLiteral || token() === SyntaxKind.BigIntLiteral || token() === SyntaxKind.StringLiteral) && !scanner.hasPrecedingLineBreak();
6932        }
6933
6934        function isDeclaration(): boolean {
6935            while (true) {
6936                switch (token()) {
6937                    case SyntaxKind.VarKeyword:
6938                    case SyntaxKind.LetKeyword:
6939                    case SyntaxKind.ConstKeyword:
6940                    case SyntaxKind.FunctionKeyword:
6941                    case SyntaxKind.ClassKeyword:
6942                    case SyntaxKind.EnumKeyword:
6943                        return true;
6944                    case SyntaxKind.StructKeyword:
6945                        return inEtsContext();
6946                    case SyntaxKind.AtToken:
6947                        return inEtsAnnotationContext() && nextToken() === SyntaxKind.InterfaceKeyword;
6948                    // 'declare', 'module', 'namespace', 'interface'* and 'type' are all legal JavaScript identifiers;
6949                    // however, an identifier cannot be followed by another identifier on the same line. This is what we
6950                    // count on to parse out the respective declarations. For instance, we exploit this to say that
6951                    //
6952                    //    namespace n
6953                    //
6954                    // can be none other than the beginning of a namespace declaration, but need to respect that JavaScript sees
6955                    //
6956                    //    namespace
6957                    //    n
6958                    //
6959                    // as the identifier 'namespace' on one line followed by the identifier 'n' on another.
6960                    // We need to look one token ahead to see if it permissible to try parsing a declaration.
6961                    //
6962                    // *Note*: 'interface' is actually a strict mode reserved word. So while
6963                    //
6964                    //   "use strict"
6965                    //   interface
6966                    //   I {}
6967                    //
6968                    // could be legal, it would add complexity for very little gain.
6969                    case SyntaxKind.InterfaceKeyword:
6970                    case SyntaxKind.TypeKeyword:
6971                        return nextTokenIsIdentifierOnSameLine();
6972                    case SyntaxKind.ModuleKeyword:
6973                    case SyntaxKind.NamespaceKeyword:
6974                        return nextTokenIsIdentifierOrStringLiteralOnSameLine();
6975                    case SyntaxKind.AbstractKeyword:
6976                    case SyntaxKind.AccessorKeyword:
6977                    case SyntaxKind.AsyncKeyword:
6978                    case SyntaxKind.DeclareKeyword:
6979                    case SyntaxKind.PrivateKeyword:
6980                    case SyntaxKind.ProtectedKeyword:
6981                    case SyntaxKind.PublicKeyword:
6982                    case SyntaxKind.ReadonlyKeyword:
6983                        nextToken();
6984                        // ASI takes effect for this modifier.
6985                        if (scanner.hasPrecedingLineBreak()) {
6986                            return false;
6987                        }
6988                        continue;
6989
6990                    case SyntaxKind.GlobalKeyword:
6991                        nextToken();
6992                        return token() === SyntaxKind.OpenBraceToken || token() === SyntaxKind.Identifier || token() === SyntaxKind.ExportKeyword;
6993
6994                    case SyntaxKind.ImportKeyword:
6995                        nextToken();
6996                        return token() === SyntaxKind.StringLiteral || token() === SyntaxKind.AsteriskToken ||
6997                            token() === SyntaxKind.OpenBraceToken || tokenIsIdentifierOrKeyword(token());
6998                    case SyntaxKind.ExportKeyword:
6999                        let currentToken = nextToken();
7000                        if (currentToken === SyntaxKind.TypeKeyword) {
7001                            currentToken = lookAhead(nextToken);
7002                        }
7003                        if (currentToken === SyntaxKind.EqualsToken || currentToken === SyntaxKind.AsteriskToken ||
7004                            currentToken === SyntaxKind.OpenBraceToken || currentToken === SyntaxKind.DefaultKeyword ||
7005                            currentToken === SyntaxKind.AsKeyword) {
7006                            return true;
7007                        }
7008                        continue;
7009
7010                    case SyntaxKind.StaticKeyword:
7011                        nextToken();
7012                        continue;
7013                    default:
7014                        return false;
7015                }
7016            }
7017        }
7018
7019        function isStartOfDeclaration(): boolean {
7020            return lookAhead(isDeclaration);
7021        }
7022
7023        function isStartOfStatement(): boolean {
7024            switch (token()) {
7025                case SyntaxKind.AtToken:
7026                case SyntaxKind.SemicolonToken:
7027                case SyntaxKind.OpenBraceToken:
7028                case SyntaxKind.VarKeyword:
7029                case SyntaxKind.LetKeyword:
7030                case SyntaxKind.FunctionKeyword:
7031                case SyntaxKind.ClassKeyword:
7032                case SyntaxKind.EnumKeyword:
7033                case SyntaxKind.IfKeyword:
7034                case SyntaxKind.DoKeyword:
7035                case SyntaxKind.WhileKeyword:
7036                case SyntaxKind.ForKeyword:
7037                case SyntaxKind.ContinueKeyword:
7038                case SyntaxKind.BreakKeyword:
7039                case SyntaxKind.ReturnKeyword:
7040                case SyntaxKind.WithKeyword:
7041                case SyntaxKind.SwitchKeyword:
7042                case SyntaxKind.ThrowKeyword:
7043                case SyntaxKind.TryKeyword:
7044                case SyntaxKind.DebuggerKeyword:
7045                // 'catch' and 'finally' do not actually indicate that the code is part of a statement,
7046                // however, we say they are here so that we may gracefully parse them and error later.
7047                // falls through
7048                case SyntaxKind.CatchKeyword:
7049                case SyntaxKind.FinallyKeyword:
7050                    return true;
7051                case SyntaxKind.StructKeyword:
7052                    return inEtsContext();
7053
7054                case SyntaxKind.ImportKeyword:
7055                    return isStartOfDeclaration() || lookAhead(nextTokenIsOpenParenOrLessThanOrDot);
7056
7057                case SyntaxKind.ConstKeyword:
7058                case SyntaxKind.ExportKeyword:
7059                    return isStartOfDeclaration();
7060
7061                case SyntaxKind.AsyncKeyword:
7062                case SyntaxKind.DeclareKeyword:
7063                case SyntaxKind.InterfaceKeyword:
7064                case SyntaxKind.ModuleKeyword:
7065                case SyntaxKind.NamespaceKeyword:
7066                case SyntaxKind.TypeKeyword:
7067                case SyntaxKind.GlobalKeyword:
7068                    // When these don't start a declaration, they're an identifier in an expression statement
7069                    return true;
7070
7071                case SyntaxKind.AccessorKeyword:
7072                case SyntaxKind.PublicKeyword:
7073                case SyntaxKind.PrivateKeyword:
7074                case SyntaxKind.ProtectedKeyword:
7075                case SyntaxKind.StaticKeyword:
7076                case SyntaxKind.ReadonlyKeyword:
7077                    // When these don't start a declaration, they may be the start of a class member if an identifier
7078                    // immediately follows. Otherwise they're an identifier in an expression statement.
7079                    return isStartOfDeclaration() || !lookAhead(nextTokenIsIdentifierOrKeywordOnSameLine);
7080
7081                default:
7082                    return isStartOfExpression();
7083            }
7084        }
7085
7086        function nextTokenIsBindingIdentifierOrStartOfDestructuring() {
7087            nextToken();
7088            return isBindingIdentifier() || token() === SyntaxKind.OpenBraceToken || token() === SyntaxKind.OpenBracketToken;
7089        }
7090
7091        function isLetDeclaration() {
7092            // In ES6 'let' always starts a lexical declaration if followed by an identifier or {
7093            // or [.
7094            return lookAhead(nextTokenIsBindingIdentifierOrStartOfDestructuring);
7095        }
7096
7097        function parseStatement(): Statement {
7098            switch (token()) {
7099                case SyntaxKind.SemicolonToken:
7100                    return parseEmptyStatement();
7101                case SyntaxKind.OpenBraceToken:
7102                    return parseBlock(/*ignoreMissingOpenBrace*/ false);
7103                case SyntaxKind.VarKeyword:
7104                    return parseVariableStatement(getNodePos(), hasPrecedingJSDocComment(), /*decorators*/ undefined, /*modifiers*/ undefined);
7105                case SyntaxKind.LetKeyword:
7106                    if (isLetDeclaration()) {
7107                        return parseVariableStatement(getNodePos(), hasPrecedingJSDocComment(), /*decorators*/ undefined, /*modifiers*/ undefined);
7108                    }
7109                    break;
7110                case SyntaxKind.FunctionKeyword:
7111                    return parseFunctionDeclaration(getNodePos(), hasPrecedingJSDocComment(), /*decorators*/ undefined, /*modifiers*/ undefined);
7112                case SyntaxKind.StructKeyword:
7113                    if (inEtsContext()) {
7114                        return parseStructDeclaration(getNodePos(), hasPrecedingJSDocComment(), /*decorators*/ undefined, /*modifiers*/ undefined);
7115                    }
7116                    break;
7117                case SyntaxKind.ClassKeyword:
7118                    return parseClassDeclaration(getNodePos(), hasPrecedingJSDocComment(), /*decorators*/ undefined, /*modifiers*/ undefined);
7119                case SyntaxKind.IfKeyword:
7120                    return parseIfStatement();
7121                case SyntaxKind.DoKeyword:
7122                    return parseDoStatement();
7123                case SyntaxKind.WhileKeyword:
7124                    return parseWhileStatement();
7125                case SyntaxKind.ForKeyword:
7126                    return parseForOrForInOrForOfStatement();
7127                case SyntaxKind.ContinueKeyword:
7128                    return parseBreakOrContinueStatement(SyntaxKind.ContinueStatement);
7129                case SyntaxKind.BreakKeyword:
7130                    return parseBreakOrContinueStatement(SyntaxKind.BreakStatement);
7131                case SyntaxKind.ReturnKeyword:
7132                    return parseReturnStatement();
7133                case SyntaxKind.WithKeyword:
7134                    return parseWithStatement();
7135                case SyntaxKind.SwitchKeyword:
7136                    return parseSwitchStatement();
7137                case SyntaxKind.ThrowKeyword:
7138                    return parseThrowStatement();
7139                case SyntaxKind.TryKeyword:
7140                // Include 'catch' and 'finally' for error recovery.
7141                // falls through
7142                case SyntaxKind.CatchKeyword:
7143                case SyntaxKind.FinallyKeyword:
7144                    return parseTryStatement();
7145                case SyntaxKind.DebuggerKeyword:
7146                    return parseDebuggerStatement();
7147                case SyntaxKind.AtToken:
7148                    return parseDeclaration();
7149                case SyntaxKind.AsyncKeyword:
7150                case SyntaxKind.InterfaceKeyword:
7151                case SyntaxKind.TypeKeyword:
7152                case SyntaxKind.ModuleKeyword:
7153                case SyntaxKind.NamespaceKeyword:
7154                case SyntaxKind.DeclareKeyword:
7155                case SyntaxKind.ConstKeyword:
7156                case SyntaxKind.EnumKeyword:
7157                case SyntaxKind.ExportKeyword:
7158                case SyntaxKind.ImportKeyword:
7159                case SyntaxKind.PrivateKeyword:
7160                case SyntaxKind.ProtectedKeyword:
7161                case SyntaxKind.PublicKeyword:
7162                case SyntaxKind.AbstractKeyword:
7163                case SyntaxKind.AccessorKeyword:
7164                case SyntaxKind.StaticKeyword:
7165                case SyntaxKind.ReadonlyKeyword:
7166                case SyntaxKind.GlobalKeyword:
7167                    if (isStartOfDeclaration()) {
7168                        return parseDeclaration();
7169                    }
7170                    break;
7171            }
7172            return parseExpressionOrLabeledStatement();
7173        }
7174
7175        function isDeclareModifier(modifier: Modifier) {
7176            return modifier.kind === SyntaxKind.DeclareKeyword;
7177        }
7178
7179        function parseAnnotationDeclaration(pos: number, hasJSDoc: boolean, decorators: NodeArray<Decorator> | undefined, modifiers: NodeArray<Modifier> | undefined): AnnotationDeclaration {
7180            const atTokenPos = scanner.getTokenPos();
7181            parseExpected(SyntaxKind.AtToken);
7182            const interfaceTokenPos = scanner.getTokenPos();
7183            parseExpected(SyntaxKind.InterfaceKeyword);
7184
7185            // Prevent any tokens between '@' and 'interface'
7186            if (interfaceTokenPos - atTokenPos > 1) {
7187                parseErrorAt(atTokenPos + 1, interfaceTokenPos, Diagnostics.In_annotation_declaration_any_symbols_between_and_interface_are_forbidden);
7188            }
7189
7190            const name = createIdentifier(isBindingIdentifier());
7191            let members;
7192            if (parseExpected(SyntaxKind.OpenBraceToken)) {
7193                members = parseAnnotationMembers();
7194                parseExpected(SyntaxKind.CloseBraceToken);
7195            }
7196            else {
7197                members = createMissingList<AnnotationElement>();
7198            }
7199            const node = factory.createAnnotationDeclaration(combineDecoratorsAndModifiers(decorators, modifiers), name, members);
7200            return withJSDoc(finishNode(node, pos), hasJSDoc);
7201        }
7202
7203        function parseDeclaration(): Statement {
7204            // `parseListElement` attempted to get the reused node at this position,
7205            // but the ambient context flag was not yet set, so the node appeared
7206            // not reusable in that context.
7207            const pos = getNodePos();
7208            const hasJSDoc = hasPrecedingJSDocComment();
7209            const decorators = parseDecorators();
7210
7211            if (token() === SyntaxKind.FunctionKeyword || token() === SyntaxKind.ExportKeyword) {
7212                if (hasEtsExtendDecoratorNames(decorators, sourceFileCompilerOptions)) {
7213                    const extendEtsComponentDecoratorNames = getEtsExtendDecoratorsComponentNames(decorators, sourceFileCompilerOptions);
7214                    if (extendEtsComponentDecoratorNames.length > 0) {
7215                        sourceFileCompilerOptions.ets?.extend.components.forEach(({ name, type, instance }) => {
7216                            if (name === last(extendEtsComponentDecoratorNames)) {
7217                                extendEtsComponentDeclaration = { name, type, instance };
7218                            }
7219                        });
7220                    }
7221                    setEtsExtendComponentsContext(!!extendEtsComponentDeclaration);
7222                }
7223                else if (hasEtsStylesDecoratorNames(decorators, sourceFileCompilerOptions)) {
7224                    const stylesEtsComponentDecoratorNames = getEtsStylesDecoratorComponentNames(decorators, sourceFileCompilerOptions);
7225                    if (stylesEtsComponentDecoratorNames.length > 0) {
7226                        stylesEtsComponentDeclaration = sourceFileCompilerOptions.ets?.styles.component;
7227                    }
7228                    setEtsStylesComponentsContext(!!stylesEtsComponentDeclaration);
7229                }
7230                else {
7231                    setEtsComponentsContext(isTokenInsideBuilder(decorators, sourceFileCompilerOptions));
7232                }
7233            }
7234
7235            const modifiers = parseModifiers();
7236            const isAmbient = some(modifiers, isDeclareModifier);
7237            if (isAmbient) {
7238                const node = tryReuseAmbientDeclaration(pos);
7239                if (node) {
7240                    return node;
7241                }
7242
7243                for (const m of modifiers!) {
7244                    (m as Mutable<Node>).flags |= NodeFlags.Ambient;
7245                }
7246                return doInsideOfContext(NodeFlags.Ambient, () => parseDeclarationWorker(pos, hasJSDoc, decorators, modifiers));
7247            }
7248            else {
7249                return parseDeclarationWorker(pos, hasJSDoc, decorators, modifiers);
7250            }
7251        }
7252
7253        function tryReuseAmbientDeclaration(pos: number): Statement | undefined {
7254            return doInsideOfContext(NodeFlags.Ambient, () => {
7255                const node = currentNode(parsingContext, pos);
7256                if (node) {
7257                    return consumeNode(node) as Statement;
7258                }
7259            });
7260        }
7261
7262        function parseDeclarationWorker(pos: number, hasJSDoc: boolean, decorators: NodeArray<Decorator> | undefined, modifiers: NodeArray<Modifier> | undefined): Statement {
7263            switch (token()) {
7264                case SyntaxKind.VarKeyword:
7265                case SyntaxKind.LetKeyword:
7266                case SyntaxKind.ConstKeyword:
7267                    return parseVariableStatement(pos, hasJSDoc, decorators, modifiers);
7268                case SyntaxKind.FunctionKeyword:
7269                    return parseFunctionDeclaration(pos, hasJSDoc, decorators, modifiers);
7270                case SyntaxKind.ClassKeyword:
7271                    return parseClassDeclaration(pos, hasJSDoc, decorators, modifiers);
7272                case SyntaxKind.StructKeyword:
7273                    if (inEtsContext()) {
7274                        return parseStructDeclaration(pos, hasJSDoc, decorators, modifiers);
7275                    }
7276                    return parseDeclarationDefault(pos,decorators, modifiers);
7277                case SyntaxKind.AtToken:
7278                    if (inEtsAnnotationContext() &&
7279                        lookAhead(() => nextToken() === SyntaxKind.InterfaceKeyword)) {
7280                        return parseAnnotationDeclaration(pos, hasJSDoc, decorators, modifiers);
7281                    }
7282                    return parseDeclarationDefault(pos,decorators, modifiers);
7283                case SyntaxKind.InterfaceKeyword:
7284                    return parseInterfaceDeclaration(pos, hasJSDoc, decorators, modifiers);
7285                case SyntaxKind.TypeKeyword:
7286                    return parseTypeAliasDeclaration(pos, hasJSDoc, decorators, modifiers);
7287                case SyntaxKind.EnumKeyword:
7288                    return parseEnumDeclaration(pos, hasJSDoc, decorators, modifiers);
7289                case SyntaxKind.GlobalKeyword:
7290                case SyntaxKind.ModuleKeyword:
7291                case SyntaxKind.NamespaceKeyword:
7292                    return parseModuleDeclaration(pos, hasJSDoc, decorators, modifiers);
7293                case SyntaxKind.ImportKeyword:
7294                    return parseImportDeclarationOrImportEqualsDeclaration(pos, hasJSDoc, decorators, modifiers);
7295                case SyntaxKind.ExportKeyword:
7296                    nextToken();
7297                    switch (token()) {
7298                        case SyntaxKind.DefaultKeyword:
7299                        case SyntaxKind.EqualsToken:
7300                            return parseExportAssignment(pos, hasJSDoc, decorators, modifiers);
7301                        case SyntaxKind.AsKeyword:
7302                            return parseNamespaceExportDeclaration(pos, hasJSDoc, decorators, modifiers);
7303                        default:
7304                            return parseExportDeclaration(pos, hasJSDoc, decorators, modifiers);
7305                    }
7306                default:
7307                    return parseDeclarationDefault(pos,decorators, modifiers);
7308            }
7309        }
7310
7311        function parseDeclarationDefault(pos: number,decorators: NodeArray<Decorator> | undefined, modifiers: NodeArray<Modifier> | undefined): Statement {
7312            if (decorators || modifiers) {
7313                // We reached this point because we encountered decorators and/or modifiers and assumed a declaration
7314                // would follow. For recovery and error reporting purposes, return an incomplete declaration.
7315                const missing = createMissingNode<MissingDeclaration>(SyntaxKind.MissingDeclaration, /*reportAtCurrentPosition*/ true, Diagnostics.Declaration_expected);
7316                setTextRangePos(missing, pos);
7317                missing.illegalDecorators = decorators;
7318                missing.modifiers = modifiers;
7319                return missing;
7320            }
7321            return undefined!; // TODO: GH#18217
7322        }
7323
7324        function nextTokenIsIdentifierOrStringLiteralOnSameLine() {
7325            nextToken();
7326            return !scanner.hasPrecedingLineBreak() && (isIdentifier() || token() === SyntaxKind.StringLiteral);
7327        }
7328
7329        function parseFunctionBlockOrSemicolon(flags: SignatureFlags, diagnosticMessage?: DiagnosticMessage): Block | undefined {
7330            if (token() !== SyntaxKind.OpenBraceToken) {
7331                if (flags & SignatureFlags.Type) {
7332                    parseTypeMemberSemicolon();
7333                    return;
7334                }
7335                if (canParseSemicolon()) {
7336                    parseSemicolon();
7337                    return;
7338                }
7339            }
7340            return parseFunctionBlock(flags, diagnosticMessage);
7341        }
7342
7343        // DECLARATIONS
7344
7345        function parseArrayBindingElement(): ArrayBindingElement {
7346            const pos = getNodePos();
7347            if (token() === SyntaxKind.CommaToken) {
7348                return finishNode(factory.createOmittedExpression(), pos);
7349            }
7350            const dotDotDotToken = parseOptionalToken(SyntaxKind.DotDotDotToken);
7351            const name = parseIdentifierOrPattern();
7352            const initializer = parseInitializer();
7353            return finishNode(factory.createBindingElement(dotDotDotToken, /*propertyName*/ undefined, name, initializer), pos);
7354        }
7355
7356        function parseObjectBindingElement(): BindingElement {
7357            const pos = getNodePos();
7358            const dotDotDotToken = parseOptionalToken(SyntaxKind.DotDotDotToken);
7359            const tokenIsIdentifier = isBindingIdentifier();
7360            let propertyName: PropertyName | undefined = parsePropertyName();
7361            let name: BindingName;
7362            if (tokenIsIdentifier && token() !== SyntaxKind.ColonToken) {
7363                name = propertyName as Identifier;
7364                propertyName = undefined;
7365            }
7366            else {
7367                parseExpected(SyntaxKind.ColonToken);
7368                name = parseIdentifierOrPattern();
7369            }
7370            const initializer = parseInitializer();
7371            return finishNode(factory.createBindingElement(dotDotDotToken, propertyName, name, initializer), pos);
7372        }
7373
7374        function parseObjectBindingPattern(): ObjectBindingPattern {
7375            const pos = getNodePos();
7376            parseExpected(SyntaxKind.OpenBraceToken);
7377            const elements = parseDelimitedList(ParsingContext.ObjectBindingElements, parseObjectBindingElement);
7378            parseExpected(SyntaxKind.CloseBraceToken);
7379            return finishNode(factory.createObjectBindingPattern(elements), pos);
7380        }
7381
7382        function parseArrayBindingPattern(): ArrayBindingPattern {
7383            const pos = getNodePos();
7384            parseExpected(SyntaxKind.OpenBracketToken);
7385            const elements = parseDelimitedList(ParsingContext.ArrayBindingElements, parseArrayBindingElement);
7386            parseExpected(SyntaxKind.CloseBracketToken);
7387            return finishNode(factory.createArrayBindingPattern(elements), pos);
7388        }
7389
7390        function isBindingIdentifierOrPrivateIdentifierOrPattern() {
7391            return token() === SyntaxKind.OpenBraceToken
7392                || token() === SyntaxKind.OpenBracketToken
7393                || token() === SyntaxKind.PrivateIdentifier
7394                || isBindingIdentifier();
7395        }
7396
7397        function parseIdentifierOrPattern(privateIdentifierDiagnosticMessage?: DiagnosticMessage): Identifier | BindingPattern {
7398            if (token() === SyntaxKind.OpenBracketToken) {
7399                return parseArrayBindingPattern();
7400            }
7401            if (token() === SyntaxKind.OpenBraceToken) {
7402                return parseObjectBindingPattern();
7403            }
7404            return parseBindingIdentifier(privateIdentifierDiagnosticMessage);
7405        }
7406
7407        function parseVariableDeclarationAllowExclamation() {
7408            return parseVariableDeclaration(/*allowExclamation*/ true);
7409        }
7410
7411        function parseVariableDeclaration(allowExclamation?: boolean): VariableDeclaration {
7412            const pos = getNodePos();
7413            const hasJSDoc = hasPrecedingJSDocComment();
7414            const name = parseIdentifierOrPattern(Diagnostics.Private_identifiers_are_not_allowed_in_variable_declarations);
7415            let exclamationToken: ExclamationToken | undefined;
7416            if (allowExclamation && name.kind === SyntaxKind.Identifier &&
7417                token() === SyntaxKind.ExclamationToken && !scanner.hasPrecedingLineBreak()) {
7418                exclamationToken = parseTokenNode<Token<SyntaxKind.ExclamationToken>>();
7419            }
7420            const type = parseTypeAnnotation();
7421            const initializer = isInOrOfKeyword(token()) ? undefined : parseInitializer();
7422            const node = factory.createVariableDeclaration(name, exclamationToken, type, initializer);
7423            return withJSDoc(finishNode(node, pos), hasJSDoc);
7424        }
7425
7426        function parseVariableDeclarationList(inForStatementInitializer: boolean): VariableDeclarationList {
7427            const pos = getNodePos();
7428
7429            let flags: NodeFlags = 0;
7430            switch (token()) {
7431                case SyntaxKind.VarKeyword:
7432                    break;
7433                case SyntaxKind.LetKeyword:
7434                    flags |= NodeFlags.Let;
7435                    break;
7436                case SyntaxKind.ConstKeyword:
7437                    flags |= NodeFlags.Const;
7438                    break;
7439                default:
7440                    Debug.fail();
7441            }
7442
7443            nextToken();
7444
7445            // The user may have written the following:
7446            //
7447            //    for (let of X) { }
7448            //
7449            // In this case, we want to parse an empty declaration list, and then parse 'of'
7450            // as a keyword. The reason this is not automatic is that 'of' is a valid identifier.
7451            // So we need to look ahead to determine if 'of' should be treated as a keyword in
7452            // this context.
7453            // The checker will then give an error that there is an empty declaration list.
7454            let declarations: readonly VariableDeclaration[];
7455            if (token() === SyntaxKind.OfKeyword && lookAhead(canFollowContextualOfKeyword)) {
7456                declarations = createMissingList<VariableDeclaration>();
7457            }
7458            else {
7459                const savedDisallowIn = inDisallowInContext();
7460                setDisallowInContext(inForStatementInitializer);
7461
7462                declarations = parseDelimitedList(ParsingContext.VariableDeclarations,
7463                    inForStatementInitializer ? parseVariableDeclaration : parseVariableDeclarationAllowExclamation);
7464
7465                setDisallowInContext(savedDisallowIn);
7466            }
7467
7468            return finishNode(factory.createVariableDeclarationList(declarations, flags), pos);
7469        }
7470
7471        function canFollowContextualOfKeyword(): boolean {
7472            return nextTokenIsIdentifier() && nextToken() === SyntaxKind.CloseParenToken;
7473        }
7474
7475        function parseVariableStatement(pos: number, hasJSDoc: boolean, decorators: NodeArray<Decorator> | undefined, modifiers: NodeArray<Modifier> | undefined): VariableStatement {
7476            const declarationList = parseVariableDeclarationList(/*inForStatementInitializer*/ false);
7477            parseSemicolon();
7478            const node = factory.createVariableStatement(modifiers, declarationList);
7479            // Decorators are not allowed on a variable statement, so we keep track of them to report them in the grammar checker.
7480            node.illegalDecorators = decorators;
7481            return withJSDoc(finishNode(node, pos), hasJSDoc);
7482        }
7483
7484        function parseFunctionDeclaration(pos: number, hasJSDoc: boolean, decorators: NodeArray<Decorator> | undefined, modifiers: NodeArray<Modifier> | undefined): FunctionDeclaration {
7485            const savedAwaitContext = inAwaitContext();
7486
7487            const modifierFlags = modifiersToFlags(modifiers);
7488            parseExpected(SyntaxKind.FunctionKeyword);
7489            const asteriskToken = parseOptionalToken(SyntaxKind.AsteriskToken);
7490            // We don't parse the name here in await context, instead we will report a grammar error in the checker.
7491            const name = modifierFlags & ModifierFlags.Default ? parseOptionalBindingIdentifier() : parseBindingIdentifier();
7492            if(name && hasEtsStylesDecoratorNames(decorators, sourceFileCompilerOptions)) {
7493                fileStylesComponents.set(name.escapedText.toString(), SyntaxKind.FunctionDeclaration);
7494            }
7495            const originalUICallbackContext = inUICallbackContext();
7496            setEtsBuilderContext(hasEtsBuilderDecoratorNames(decorators, sourceFileCompilerOptions));
7497            setUICallbackContext(inBuilderContext());
7498            const isGenerator = asteriskToken ? SignatureFlags.Yield : SignatureFlags.None;
7499            const isAsync = modifierFlags & ModifierFlags.Async ? SignatureFlags.Await : SignatureFlags.None;
7500            const typeParameters = inEtsStylesComponentsContext() && stylesEtsComponentDeclaration ? parseEtsTypeParameters(scanner.getStartPos()) : parseTypeParameters();
7501            if (modifierFlags & ModifierFlags.Export) setAwaitContext(/*value*/ true);
7502            const parameters = parseParameters(isGenerator | isAsync);
7503            const typeStartPos = scanner.getStartPos();
7504            const type = getFunctionDeclarationReturnType();
7505            const body = parseFunctionBlockOrSemicolon(isGenerator | isAsync, Diagnostics.or_expected);
7506            setEtsBuilderContext(false);
7507            setUICallbackContext(originalUICallbackContext);
7508            setEtsExtendComponentsContext(false);
7509            extendEtsComponentDeclaration = undefined;
7510            setEtsStylesComponentsContext(false);
7511            stylesEtsComponentDeclaration = undefined;
7512            setEtsComponentsContext(inBuildContext());
7513            setAwaitContext(savedAwaitContext);
7514            const node = factory.createFunctionDeclaration(modifiers, asteriskToken, name, typeParameters, parameters, type, body);
7515            (node as Mutable<FunctionDeclaration>).illegalDecorators = decorators;
7516            return withJSDoc(finishNode(node, pos), hasJSDoc);
7517
7518            function getFunctionDeclarationReturnType(): TypeNode | undefined {
7519                let returnType = parseReturnType(SyntaxKind.ColonToken, /*isType*/ false);
7520                // If function decorated by Extend and type is not defined, then will use Ets Extend Components Type
7521                if (!returnType && extendEtsComponentDeclaration && inEtsExtendComponentsContext()) {
7522                    returnType = finishVirtualNode(factory.createTypeReferenceNode(
7523                        finishVirtualNode(factory.createIdentifier(extendEtsComponentDeclaration.type), typeStartPos, typeStartPos)),
7524                        typeStartPos, typeStartPos);
7525                }
7526                // If function decorated by Styles and type is not defined, then will use Ets Styles Components Type
7527                if (!returnType && stylesEtsComponentDeclaration && inEtsStylesComponentsContext()) {
7528                    returnType = finishVirtualNode(factory.createTypeReferenceNode(
7529                        finishVirtualNode(factory.createIdentifier(stylesEtsComponentDeclaration.type), typeStartPos, typeStartPos)),
7530                        typeStartPos, typeStartPos);
7531                }
7532                return returnType;
7533            }
7534        }
7535
7536        function parseConstructorName() {
7537            if (token() === SyntaxKind.ConstructorKeyword) {
7538                return parseExpected(SyntaxKind.ConstructorKeyword);
7539            }
7540            if (token() === SyntaxKind.StringLiteral && lookAhead(nextToken) === SyntaxKind.OpenParenToken) {
7541                return tryParse(() => {
7542                    const literalNode = parseLiteralNode();
7543                    return literalNode.text === "constructor" ? literalNode : undefined;
7544                });
7545            }
7546        }
7547
7548        function tryParseConstructorDeclaration(pos: number, hasJSDoc: boolean, decorators: NodeArray<Decorator> | undefined, modifiers: NodeArray<Modifier> | undefined): ConstructorDeclaration | undefined {
7549            return tryParse(() => {
7550                if (parseConstructorName()) {
7551                    const typeParameters = parseTypeParameters();
7552                    const parameters = parseParameters(SignatureFlags.None);
7553                    const type = parseReturnType(SyntaxKind.ColonToken, /*isType*/ false);
7554                    const body = parseFunctionBlockOrSemicolon(SignatureFlags.None, Diagnostics.or_expected);
7555                    const node = factory.createConstructorDeclaration(modifiers, parameters, body);
7556
7557                    // Attach invalid nodes if they exist so that we can report them in the grammar checker.
7558                    (node as Mutable<ConstructorDeclaration>).illegalDecorators = decorators;
7559                    (node as Mutable<ConstructorDeclaration>).typeParameters = typeParameters;
7560                    (node as Mutable<ConstructorDeclaration>).type = type;
7561                    return withJSDoc(finishNode(node, pos), hasJSDoc);
7562                }
7563            });
7564        }
7565
7566
7567        function isTokenInsideStructBuild(methodName: PropertyName): boolean {
7568            const renderMethod = sourceFileCompilerOptions.ets?.render?.method?.find(render => render === "build") ?? "build";
7569
7570            if (methodName.kind === SyntaxKind.Identifier && methodName.escapedText === renderMethod) {
7571                return true;
7572            }
7573            return false;
7574        }
7575
7576        function isTokenInsideStructBuilder(decorators: NodeArray<Decorator> | undefined): boolean {
7577            return isTokenInsideBuilder(decorators, sourceFileCompilerOptions);
7578        }
7579
7580        function isTokenInsideStructPageTransition(methodName: PropertyName): boolean {
7581            const renderMethod = sourceFileCompilerOptions.ets?.render?.method?.find(render => render === "pageTransition") ?? "pageTransition";
7582
7583            if (methodName.kind === SyntaxKind.Identifier && methodName.escapedText === renderMethod) {
7584                return true;
7585            }
7586            return false;
7587        }
7588
7589        function parseMethodDeclaration(
7590            pos: number,
7591            hasJSDoc: boolean,
7592            decorators: NodeArray<Decorator> | undefined,
7593            modifiers: NodeArray<Modifier> | undefined,
7594            asteriskToken: AsteriskToken | undefined,
7595            name: PropertyName,
7596            questionToken: QuestionToken | undefined,
7597            exclamationToken: ExclamationToken | undefined,
7598            diagnosticMessage?: DiagnosticMessage
7599        ): MethodDeclaration {
7600            const methodName = getPropertyNameForPropertyNameNode(name)?.toString();
7601            const orignalEtsBuildContext = inBuildContext();
7602            const orignalEtsBuilderContext = inBuilderContext();
7603            const orignalUICallbackContext = inUICallbackContext();
7604            setEtsBuildContext(methodName === sourceFileCompilerOptions?.ets?.render?.method?.find(render => render === "build"));
7605            setEtsBuilderContext(hasEtsBuilderDecoratorNames(decorators, sourceFileCompilerOptions));
7606            setUICallbackContext(inBuildContext() || inBuilderContext());
7607            if (inStructContext() && hasEtsStylesDecoratorNames(decorators, sourceFileCompilerOptions)) {
7608                if (methodName && currentStructName) {
7609                    structStylesComponents.set(methodName, { structName: currentStructName, kind: SyntaxKind.MethodDeclaration });
7610                }
7611                const stylesEtsComponentDecoratorNames = getEtsStylesDecoratorComponentNames(decorators, sourceFileCompilerOptions);
7612                if (stylesEtsComponentDecoratorNames.length > 0) {
7613                    stylesEtsComponentDeclaration = sourceFileCompilerOptions.ets?.styles.component;
7614                }
7615                setEtsStylesComponentsContext(!!stylesEtsComponentDeclaration);
7616            }
7617            const orignalEtsComponentsContext: boolean = inEtsComponentsContext();
7618            setEtsComponentsContext(inStructContext() && (isTokenInsideStructBuild(name) || isTokenInsideStructBuilder(decorators) ||
7619                isTokenInsideStructPageTransition(name)));
7620            const isGenerator = asteriskToken ? SignatureFlags.Yield : SignatureFlags.None;
7621            const isAsync = some(modifiers, isAsyncModifier) ? SignatureFlags.Await : SignatureFlags.None;
7622            const typeParameters = inEtsStylesComponentsContext() && stylesEtsComponentDeclaration ? parseEtsTypeParameters(pos) : parseTypeParameters();
7623            const parameters = parseParameters(isGenerator | isAsync);
7624            const typeStartPos = scanner.getStartPos();
7625            const type = getMethodDeclarationReturnType();
7626            const body = parseFunctionBlockOrSemicolon(isGenerator | isAsync, diagnosticMessage);
7627            const node = factory.createMethodDeclaration(
7628                combineDecoratorsAndModifiers(decorators, modifiers),
7629                asteriskToken,
7630                name,
7631                questionToken,
7632                typeParameters,
7633                parameters,
7634                type,
7635                body
7636            );
7637
7638            // An exclamation token on a method is invalid syntax and will be handled by the grammar checker
7639            (node as Mutable<MethodDeclaration>).exclamationToken = exclamationToken;
7640            setEtsBuildContext(orignalEtsBuildContext);
7641            setEtsBuilderContext(orignalEtsBuilderContext);
7642            setUICallbackContext(orignalUICallbackContext);
7643            setEtsStylesComponentsContext(false);
7644            stylesEtsComponentDeclaration = undefined;
7645            setEtsComponentsContext(orignalEtsComponentsContext);
7646            return withJSDoc(finishNode(node, pos), hasJSDoc);
7647
7648            function getMethodDeclarationReturnType(): TypeNode | undefined {
7649                let returnType = parseReturnType(SyntaxKind.ColonToken, /*isType*/ false);
7650                // If function decorated by Styles and type is not defined, then will use Ets Styles Components Type
7651                if (!returnType && stylesEtsComponentDeclaration && inEtsStylesComponentsContext()) {
7652                    returnType = finishVirtualNode(factory.createTypeReferenceNode(
7653                        finishVirtualNode(factory.createIdentifier(stylesEtsComponentDeclaration.type), typeStartPos, typeStartPos)),
7654                        typeStartPos, typeStartPos);
7655                }
7656                return returnType;
7657            }
7658        }
7659
7660        function parseAnnotationPropertyDeclaration(
7661            pos: number,
7662            hasJSDoc: boolean,
7663            name: PropertyName
7664        ): AnnotationPropertyDeclaration {
7665            const type = parseTypeAnnotation();
7666            const initializer = doOutsideOfContext(NodeFlags.YieldContext | NodeFlags.AwaitContext | NodeFlags.DisallowInContext, parseInitializer);
7667            parseSemicolonAfterPropertyName(name, type, initializer);
7668            const node = factory.createAnnotationPropertyDeclaration(
7669                name,
7670                type,
7671                initializer);
7672            return withJSDoc(finishNode(node, pos), hasJSDoc);
7673        }
7674
7675        function parsePropertyDeclaration(
7676            pos: number,
7677            hasJSDoc: boolean,
7678            decorators: NodeArray<Decorator> | undefined,
7679            modifiers: NodeArray<Modifier> | undefined,
7680            name: PropertyName,
7681            questionToken: QuestionToken | undefined
7682        ): PropertyDeclaration {
7683            const exclamationToken = !questionToken && !scanner.hasPrecedingLineBreak() ? parseOptionalToken(SyntaxKind.ExclamationToken) : undefined;
7684            const type = parseTypeAnnotation();
7685            const initializer = doOutsideOfContext(NodeFlags.YieldContext | NodeFlags.AwaitContext | NodeFlags.DisallowInContext, parseInitializer);
7686            parseSemicolonAfterPropertyName(name, type, initializer);
7687            const node = factory.createPropertyDeclaration(
7688                combineDecoratorsAndModifiers(decorators, modifiers),
7689                name,
7690                questionToken || exclamationToken,
7691                type,
7692                initializer);
7693            return withJSDoc(finishNode(node, pos), hasJSDoc);
7694        }
7695
7696        function parsePropertyOrMethodDeclaration(
7697            pos: number,
7698            hasJSDoc: boolean,
7699            decorators: NodeArray<Decorator> | undefined,
7700            modifiers: NodeArray<Modifier> | undefined
7701        ): PropertyDeclaration | MethodDeclaration {
7702            const asteriskToken = parseOptionalToken(SyntaxKind.AsteriskToken);
7703            const name = parsePropertyName();
7704            // Note: this is not legal as per the grammar.  But we allow it in the parser and
7705            // report an error in the grammar checker.
7706            const questionToken = parseOptionalToken(SyntaxKind.QuestionToken);
7707            if (asteriskToken || token() === SyntaxKind.OpenParenToken || token() === SyntaxKind.LessThanToken) {
7708                return parseMethodDeclaration(pos, hasJSDoc, decorators, modifiers, asteriskToken, name, questionToken, /*exclamationToken*/ undefined, Diagnostics.or_expected);
7709            }
7710            return parsePropertyDeclaration(pos, hasJSDoc, decorators, modifiers, name, questionToken);
7711        }
7712
7713        function parseAccessorDeclaration(pos: number, hasJSDoc: boolean, decorators: NodeArray<Decorator> | undefined, modifiers: NodeArray<Modifier> | undefined, kind: AccessorDeclaration["kind"], flags: SignatureFlags): AccessorDeclaration {
7714            const name = parsePropertyName();
7715            const typeParameters = parseTypeParameters();
7716            const parameters = parseParameters(SignatureFlags.None);
7717            const type = parseReturnType(SyntaxKind.ColonToken, /*isType*/ false);
7718            const body = parseFunctionBlockOrSemicolon(flags);
7719            const node = kind === SyntaxKind.GetAccessor
7720                ? factory.createGetAccessorDeclaration(combineDecoratorsAndModifiers(decorators, modifiers), name, parameters, type, body)
7721                : factory.createSetAccessorDeclaration(combineDecoratorsAndModifiers(decorators, modifiers), name, parameters, body);
7722            // Keep track of `typeParameters` (for both) and `type` (for setters) if they were parsed those indicate grammar errors
7723            (node as Mutable<AccessorDeclaration>).typeParameters = typeParameters;
7724            if (isSetAccessorDeclaration(node)) (node as Mutable<SetAccessorDeclaration>).type = type;
7725            return withJSDoc(finishNode(node, pos), hasJSDoc);
7726        }
7727
7728        function isAnnotationMemberStart(): boolean {
7729            let idToken: SyntaxKind | undefined;
7730
7731            if (token() === SyntaxKind.AtToken) {
7732                return false;
7733            }
7734
7735            if (isModifierKind(token())) {
7736                return false;
7737            }
7738
7739            if (token() === SyntaxKind.AsteriskToken) {
7740                return false ;
7741            }
7742
7743            // Try to get the first property-like token following all modifiers.
7744            // This can either be an identifier or the 'get' or 'set' keywords.
7745            if (isLiteralPropertyName()) {
7746                idToken = token();
7747                nextToken();
7748            }
7749
7750            // Index signatures and computed properties are prohibited for annotations
7751            if (token() === SyntaxKind.OpenBracketToken) {
7752                return false;
7753            }
7754
7755            // If we were able to get any potential identifier...
7756            if (idToken !== undefined) {
7757                // If we have a non-keyword identifier, or if we have an accessor, then we no need to parse.
7758                if (isKeyword(idToken)) {
7759                    return false;
7760                }
7761
7762                // If it *is* a keyword, but not an accessor, check a little farther along
7763                // to see if it should actually be parsed as a class member.
7764                switch (token()) {
7765                    case SyntaxKind.ColonToken:         // Type Annotation for declaration
7766                    case SyntaxKind.EqualsToken:        // Initializer for declaration
7767                        return true;
7768                    default:
7769                        // Covers
7770                        //  - Semicolons     (declaration termination)
7771                        //  - Closing braces (end-of-class, must be declaration)
7772                        //  - End-of-files   (not valid, but permitted so that it gets caught later on)
7773                        //  - Line-breaks    (enabling *automatic semicolon insertion*)
7774                        return canParseSemicolon();
7775                }
7776            }
7777            return false;
7778        }
7779
7780        function isClassMemberStart(): boolean {
7781            let idToken: SyntaxKind | undefined;
7782
7783            if (token() === SyntaxKind.AtToken) {
7784                if (inEtsAnnotationContext() && lookAhead(() => nextToken() === SyntaxKind.InterfaceKeyword)) {
7785                    return false;
7786                }
7787                return true;
7788            }
7789
7790            // Eat up all modifiers, but hold on to the last one in case it is actually an identifier.
7791            while (isModifierKind(token())) {
7792                idToken = token();
7793                // If the idToken is a class modifier (protected, private, public, and static), it is
7794                // certain that we are starting to parse class member. This allows better error recovery
7795                // Example:
7796                //      public foo() ...     // true
7797                //      public @dec blah ... // true; we will then report an error later
7798                //      export public ...    // true; we will then report an error later
7799                if (isClassMemberModifier(idToken)) {
7800                    return true;
7801                }
7802
7803                nextToken();
7804            }
7805
7806            if (token() === SyntaxKind.AsteriskToken) {
7807                return true;
7808            }
7809
7810            // Try to get the first property-like token following all modifiers.
7811            // This can either be an identifier or the 'get' or 'set' keywords.
7812            if (isLiteralPropertyName()) {
7813                idToken = token();
7814                nextToken();
7815            }
7816
7817            // Index signatures and computed properties are class members; we can parse.
7818            if (token() === SyntaxKind.OpenBracketToken) {
7819                return true;
7820            }
7821
7822            // If we were able to get any potential identifier...
7823            if (idToken !== undefined) {
7824                // If we have a non-keyword identifier, or if we have an accessor, then it's safe to parse.
7825                if (!isKeyword(idToken) || idToken === SyntaxKind.SetKeyword || idToken === SyntaxKind.GetKeyword) {
7826                    return true;
7827                }
7828
7829                // If it *is* a keyword, but not an accessor, check a little farther along
7830                // to see if it should actually be parsed as a class member.
7831                switch (token()) {
7832                    case SyntaxKind.OpenParenToken:     // Method declaration
7833                    case SyntaxKind.LessThanToken:      // Generic Method declaration
7834                    case SyntaxKind.ExclamationToken:   // Non-null assertion on property name
7835                    case SyntaxKind.ColonToken:         // Type Annotation for declaration
7836                    case SyntaxKind.EqualsToken:        // Initializer for declaration
7837                    case SyntaxKind.QuestionToken:      // Not valid, but permitted so that it gets caught later on.
7838                        return true;
7839                    default:
7840                        // Covers
7841                        //  - Semicolons     (declaration termination)
7842                        //  - Closing braces (end-of-class, must be declaration)
7843                        //  - End-of-files   (not valid, but permitted so that it gets caught later on)
7844                        //  - Line-breaks    (enabling *automatic semicolon insertion*)
7845                        return canParseSemicolon();
7846                }
7847            }
7848            return false;
7849        }
7850
7851        function parseClassStaticBlockDeclaration(pos: number, hasJSDoc: boolean, decorators: NodeArray<Decorator> | undefined, modifiers: ModifiersArray | undefined): ClassStaticBlockDeclaration {
7852            parseExpectedToken(SyntaxKind.StaticKeyword);
7853            const body = parseClassStaticBlockBody();
7854            const node = withJSDoc(finishNode(factory.createClassStaticBlockDeclaration(body), pos), hasJSDoc);
7855            (node as Mutable<ClassStaticBlockDeclaration>).illegalDecorators = decorators;
7856            (node as Mutable<ClassStaticBlockDeclaration>).modifiers = modifiers;
7857            return node;
7858        }
7859
7860        function parseClassStaticBlockBody() {
7861            const savedYieldContext = inYieldContext();
7862            const savedAwaitContext = inAwaitContext();
7863
7864            setYieldContext(false);
7865            setAwaitContext(true);
7866
7867            const body = parseBlock(/*ignoreMissingOpenBrace*/ false);
7868
7869            setYieldContext(savedYieldContext);
7870            setAwaitContext(savedAwaitContext);
7871
7872            return body;
7873        }
7874
7875        function parseDecoratorExpression() {
7876            if (inAwaitContext() && token() === SyntaxKind.AwaitKeyword) {
7877                // `@await` is is disallowed in an [Await] context, but can cause parsing to go off the rails
7878                // This simply parses the missing identifier and moves on.
7879                const pos = getNodePos();
7880                const awaitExpression = parseIdentifier(Diagnostics.Expression_expected);
7881                nextToken();
7882                const memberExpression = parseMemberExpressionRest(pos, awaitExpression, /*allowOptionalChain*/ true);
7883                return parseCallExpressionRest(pos, memberExpression);
7884            }
7885            return parseLeftHandSideExpressionOrHigher();
7886        }
7887
7888        function tryParseDecorator(): Decorator | undefined {
7889            const pos = getNodePos();
7890            if (inEtsAnnotationContext() && token() === SyntaxKind.AtToken
7891                && lookAhead(() => nextToken() === SyntaxKind.InterfaceKeyword)) {
7892                    return undefined;
7893            }
7894            if (!parseOptional(SyntaxKind.AtToken)) {
7895                return undefined;
7896            }
7897            const expression = doInDecoratorContext(parseDecoratorExpression);
7898            return finishNode(factory.createDecorator(expression), pos);
7899        }
7900
7901        function parseDecorators(): NodeArray<Decorator> | undefined {
7902            const pos = getNodePos();
7903            let list, decorator;
7904            while (decorator = tryParseDecorator()) {
7905                list = append(list, decorator);
7906            }
7907            return list && createNodeArray(list, pos);
7908        }
7909
7910        function tryParseModifier(permitInvalidConstAsModifier?: boolean, stopOnStartOfClassStaticBlock?: boolean, hasSeenStaticModifier?: boolean): Modifier | undefined {
7911            const pos = getNodePos();
7912            const kind = token();
7913
7914            if (token() === SyntaxKind.ConstKeyword && permitInvalidConstAsModifier) {
7915                // We need to ensure that any subsequent modifiers appear on the same line
7916                // so that when 'const' is a standalone declaration, we don't issue an error.
7917                if (!tryParse(nextTokenIsOnSameLineAndCanFollowModifier)) {
7918                    return undefined;
7919                }
7920            }
7921            else if (stopOnStartOfClassStaticBlock && token() === SyntaxKind.StaticKeyword && lookAhead(nextTokenIsOpenBrace)) {
7922                return undefined;
7923            }
7924            else if (hasSeenStaticModifier && token() === SyntaxKind.StaticKeyword) {
7925                return undefined;
7926            }
7927            else {
7928                if (!parseAnyContextualModifier()) {
7929                    return undefined;
7930                }
7931            }
7932
7933            return finishNode(factory.createToken(kind as Modifier["kind"]), pos);
7934        }
7935
7936        function combineDecoratorsAndModifiers(decorators: NodeArray<Decorator> | undefined, modifiers: NodeArray<Modifier> | undefined): NodeArray<ModifierLike> | undefined {
7937            if (!decorators) return modifiers;
7938            if (!modifiers) return decorators;
7939            const decoratorsAndModifiers = factory.createNodeArray(concatenate<ModifierLike>(decorators, modifiers));
7940            setTextRangePosEnd(decoratorsAndModifiers, decorators.pos, modifiers.end);
7941            return decoratorsAndModifiers;
7942        }
7943
7944        function hasParamAndNoOnceDecorator(decorators: NodeArray<Decorator> | undefined): boolean {
7945            let hasParamDecorator = false;
7946            let hasOnceDecorator = false;
7947            decorators?.forEach((decorator) => {
7948                if (!ts.isIdentifier(decorator.expression)) {
7949                    return;
7950                }
7951                if (decorator.expression.escapedText === 'Param') {
7952                    hasParamDecorator = true;
7953                }
7954                else if (decorator.expression.escapedText === 'Once') {
7955                    hasOnceDecorator = true;
7956                }
7957            });
7958            return (hasParamDecorator && !hasOnceDecorator);
7959        }
7960        /*
7961         * There are situations in which a modifier like 'const' will appear unexpectedly, such as on a class member.
7962         * In those situations, if we are entirely sure that 'const' is not valid on its own (such as when ASI takes effect
7963         * and turns it into a standalone declaration), then it is better to parse it and report an error later.
7964         *
7965         * In such situations, 'permitInvalidConstAsModifier' should be set to true.
7966         */
7967        function parseModifiers(
7968            permitInvalidConstAsModifier?: boolean,
7969            stopOnStartOfClassStaticBlock?: boolean,
7970            shouldAddReadonly?: boolean
7971        ): NodeArray<Modifier> | undefined {
7972            const pos = getNodePos();
7973            let list, modifier, hasSeenStatic = false;
7974            let hasReadonly = false;
7975            while (modifier = tryParseModifier(permitInvalidConstAsModifier, stopOnStartOfClassStaticBlock, hasSeenStatic)) {
7976                if (modifier.kind === SyntaxKind.StaticKeyword) hasSeenStatic = true;
7977                if (modifier.kind === SyntaxKind.ReadonlyKeyword) {
7978                    hasReadonly = true;
7979                }
7980                list = append(list, modifier);
7981            }
7982            if (shouldAddReadonly && !hasReadonly) {
7983                const readonlyModifier = finishVirtualNode(factory.createToken(SyntaxKind.ReadonlyKeyword));
7984                list = append(list, readonlyModifier);
7985            }
7986            return list && createNodeArray(list, pos);
7987        }
7988
7989        function parseModifiersForArrowFunction(): NodeArray<Modifier> | undefined {
7990            let modifiers: NodeArray<Modifier> | undefined;
7991            if (token() === SyntaxKind.AsyncKeyword) {
7992                const pos = getNodePos();
7993                nextToken();
7994                const modifier = finishNode(factory.createToken(SyntaxKind.AsyncKeyword), pos);
7995                modifiers = createNodeArray<Modifier>([modifier], pos);
7996            }
7997            return modifiers;
7998        }
7999
8000        function parseClassElement(): ClassElement {
8001            const pos = getNodePos();
8002            if (token() === SyntaxKind.SemicolonToken) {
8003                nextToken();
8004                return finishNode(factory.createSemicolonClassElement(), pos);
8005            }
8006
8007            const hasJSDoc = hasPrecedingJSDocComment();
8008            const decorators = parseDecorators();
8009            /*
8010             *  shouldAddReadonly adds readonly modifier when the element in struct has the Param decorator
8011             *  and doesn't have Once decorator.
8012             */
8013            const shouldAddReadonly = inStructContext() && hasParamAndNoOnceDecorator(decorators);
8014            const modifiers = parseModifiers(/*permitInvalidConstAsModifier*/ true, /*stopOnStartOfClassStaticBlock*/ true, shouldAddReadonly);
8015            if (token() === SyntaxKind.StaticKeyword && lookAhead(nextTokenIsOpenBrace)) {
8016                return parseClassStaticBlockDeclaration(pos, hasJSDoc, decorators, modifiers);
8017            }
8018
8019            if (parseContextualModifier(SyntaxKind.GetKeyword)) {
8020                return parseAccessorDeclaration(pos, hasJSDoc, decorators, modifiers, SyntaxKind.GetAccessor, SignatureFlags.None);
8021            }
8022
8023            if (parseContextualModifier(SyntaxKind.SetKeyword)) {
8024                return parseAccessorDeclaration(pos, hasJSDoc, decorators, modifiers, SyntaxKind.SetAccessor, SignatureFlags.None);
8025            }
8026
8027            if (token() === SyntaxKind.ConstructorKeyword || token() === SyntaxKind.StringLiteral) {
8028                const constructorDeclaration = tryParseConstructorDeclaration(pos, hasJSDoc, decorators, modifiers);
8029                if (constructorDeclaration) {
8030                    return constructorDeclaration;
8031                }
8032            }
8033
8034            if (isIndexSignature()) {
8035                return parseIndexSignatureDeclaration(pos, hasJSDoc, decorators, modifiers);
8036            }
8037
8038            // It is very important that we check this *after* checking indexers because
8039            // the [ token can start an index signature or a computed property name
8040            if (tokenIsIdentifierOrKeyword(token()) ||
8041                token() === SyntaxKind.StringLiteral ||
8042                token() === SyntaxKind.NumericLiteral ||
8043                token() === SyntaxKind.AsteriskToken ||
8044                token() === SyntaxKind.OpenBracketToken) {
8045                const isAmbient = some(modifiers, isDeclareModifier);
8046                if (isAmbient) {
8047                    for (const m of modifiers!) {
8048                        (m as Mutable<Node>).flags |= NodeFlags.Ambient;
8049                    }
8050                    return doInsideOfContext(NodeFlags.Ambient, () => parsePropertyOrMethodDeclaration(pos, hasJSDoc, decorators, modifiers));
8051                }
8052                else {
8053                    return parsePropertyOrMethodDeclaration(pos, hasJSDoc, decorators, modifiers);
8054                }
8055            }
8056
8057            if (decorators || modifiers) {
8058                // treat this as a property declaration with a missing name.
8059                const name = createMissingNode<Identifier>(SyntaxKind.Identifier, /*reportAtCurrentPosition*/ true, Diagnostics.Declaration_expected);
8060                return parsePropertyDeclaration(pos, hasJSDoc, decorators, modifiers, name, /*questionToken*/ undefined);
8061            }
8062
8063            // 'isClassMemberStart' should have hinted not to attempt parsing.
8064            return Debug.fail("Should not have attempted to parse class member declaration.");
8065        }
8066
8067        function parseAnnotationElement(): AnnotationElement {
8068            const pos = getNodePos();
8069            if (token() === SyntaxKind.SemicolonToken) {
8070                parseErrorAt(pos, pos, Diagnostics.Unexpected_keyword_or_identifier);
8071            }
8072
8073            const hasJSDoc = hasPrecedingJSDocComment();
8074            if (token() === SyntaxKind.StaticKeyword && lookAhead(nextTokenIsOpenBrace)) {
8075                return createMissingNode<AnnotationElement>(SyntaxKind.AnnotationPropertyDeclaration, /*reportAtCurrentPosition*/ true, Diagnostics.Unexpected_keyword_or_identifier);
8076            }
8077
8078            if (parseContextualModifier(SyntaxKind.GetKeyword)) {
8079                return createMissingNode<AnnotationElement>(SyntaxKind.AnnotationPropertyDeclaration, /*reportAtCurrentPosition*/ true, Diagnostics.Unexpected_keyword_or_identifier);
8080            }
8081
8082            if (parseContextualModifier(SyntaxKind.SetKeyword)) {
8083                return createMissingNode<AnnotationElement>(SyntaxKind.AnnotationPropertyDeclaration, /*reportAtCurrentPosition*/ true, Diagnostics.Unexpected_keyword_or_identifier);
8084            }
8085
8086            if (token() === SyntaxKind.ConstructorKeyword || token() === SyntaxKind.StringLiteral) {
8087                return createMissingNode<AnnotationElement>(SyntaxKind.AnnotationPropertyDeclaration, /*reportAtCurrentPosition*/ true, Diagnostics.Unexpected_keyword_or_identifier);
8088            }
8089
8090            if (isIndexSignature()) {
8091                return createMissingNode<AnnotationElement>(SyntaxKind.AnnotationPropertyDeclaration, /*reportAtCurrentPosition*/ true, Diagnostics.Unexpected_keyword_or_identifier);
8092            }
8093
8094            if (tokenIsIdentifierOrKeyword(token())) {
8095                const name = parsePropertyName();
8096                return parseAnnotationPropertyDeclaration(pos, hasJSDoc, name);
8097            }
8098
8099            // 'isAnnotationMemberStart' should have hinted not to attempt parsing.
8100            return Debug.fail("Should not have attempted to parse annotation member declaration.");
8101        }
8102
8103        function parseClassExpression(): ClassExpression {
8104            return parseClassDeclarationOrExpression(getNodePos(), hasPrecedingJSDocComment(), /*decorators*/ undefined, /*modifiers*/ undefined, SyntaxKind.ClassExpression) as ClassExpression;
8105        }
8106
8107        function parseClassDeclaration(pos: number, hasJSDoc: boolean, decorators: NodeArray<Decorator> | undefined, modifiers: NodeArray<Modifier> | undefined): ClassDeclaration {
8108            return parseClassDeclarationOrExpression(pos, hasJSDoc, decorators, modifiers, SyntaxKind.ClassDeclaration) as ClassDeclaration;
8109        }
8110
8111        function parseStructDeclaration(pos: number, hasJSDoc: boolean, decorators: NodeArray<Decorator> | undefined, modifiers: NodeArray<Modifier> | undefined): StructDeclaration {
8112            return parseStructDeclarationOrExpression(pos, hasJSDoc, decorators, modifiers);
8113        }
8114
8115        function parseClassDeclarationOrExpression(pos: number, hasJSDoc: boolean, decorators: NodeArray<Decorator> | undefined, modifiers: NodeArray<Modifier> | undefined, kind: ClassLikeDeclaration["kind"]): ClassLikeDeclaration {
8116            const savedAwaitContext = inAwaitContext();
8117            parseExpected(SyntaxKind.ClassKeyword);
8118
8119            // We don't parse the name here in await context, instead we will report a grammar error in the checker.
8120            const name = parseNameOfClassDeclarationOrExpression();
8121            const typeParameters = parseTypeParameters();
8122            if (some(modifiers, isExportModifier)) setAwaitContext(/*value*/ true);
8123            const heritageClauses = parseHeritageClauses();
8124
8125            let members;
8126            if (parseExpected(SyntaxKind.OpenBraceToken)) {
8127                // ClassTail[Yield,Await] : (Modified) See 14.5
8128                //      ClassHeritage[?Yield,?Await]opt { ClassBody[?Yield,?Await]opt }
8129                members = parseClassMembers();
8130                parseExpected(SyntaxKind.CloseBraceToken);
8131            }
8132            else {
8133                members = createMissingList<ClassElement>();
8134            }
8135            setAwaitContext(savedAwaitContext);
8136            const node = kind === SyntaxKind.ClassDeclaration
8137                ? factory.createClassDeclaration(combineDecoratorsAndModifiers(decorators, modifiers), name, typeParameters, heritageClauses, members)
8138                : factory.createClassExpression(combineDecoratorsAndModifiers(decorators, modifiers), name, typeParameters, heritageClauses, members);
8139            return withJSDoc(finishNode(node, pos), hasJSDoc);
8140        }
8141
8142        function parseStructDeclarationOrExpression(pos: number, hasJSDoc: boolean, decorators: NodeArray<Decorator> | undefined, modifiers: NodeArray<Modifier> | undefined): StructDeclaration {
8143            const savedAwaitContext = inAwaitContext();
8144            parseExpected(SyntaxKind.StructKeyword);
8145            setStructContext(true);
8146            // We don't parse the name here in await context, instead we will report a grammar error in the checker.
8147            // struct Identifier logic is same to class Identifier
8148            const name = parseNameOfClassDeclarationOrExpression();
8149            const typeParameters = parseTypeParameters();
8150            if (some(modifiers, isExportModifier)) setAwaitContext(/*value*/ true);
8151            let heritageClauses = parseHeritageClauses();
8152            const customComponent = sourceFileCompilerOptions.ets?.customComponent;
8153            if (!heritageClauses && customComponent) {
8154                heritageClauses = createVirtualHeritageClauses(customComponent);
8155            }
8156            let members;
8157            if (parseExpected(SyntaxKind.OpenBraceToken)) {
8158                // ClassTail[Yield,Await] : (Modified) See 14.5
8159                //      ClassHeritage[?Yield,?Await]opt { ClassBody[?Yield,?Await]opt }
8160                members = parseStructMembers(pos);
8161                parseExpected(SyntaxKind.CloseBraceToken);
8162            }
8163            else {
8164                members = createMissingList<ClassElement>();
8165            }
8166            setAwaitContext(savedAwaitContext);
8167            const node = factory.createStructDeclaration(combineDecoratorsAndModifiers(decorators, modifiers), name, typeParameters, heritageClauses, members);
8168            structStylesComponents.clear();
8169            setStructContext(false);
8170            return withJSDoc(finishNode(node, pos), hasJSDoc);
8171        }
8172
8173        function createVirtualHeritageClauses(customComponent: string): NodeArray<HeritageClause> {
8174            const curPos = getNodePos();
8175            const clause = factory.createHeritageClause(
8176                SyntaxKind.ExtendsKeyword,
8177                createNodeArray([finishNode(factory.createExpressionWithTypeArguments(
8178                    finishNode(factory.createIdentifier(/*text*/ customComponent), curPos, /*end*/ undefined, /*virtual*/ true),
8179                /*typeArguments*/ undefined
8180                ), curPos)], curPos, /*end*/ undefined, /*hasTrailingComma*/ false)
8181            );
8182            return createNodeArray([finishNode(clause, curPos, /*end*/ undefined, /*virtual*/ true)], curPos, /*end*/ undefined, /*hasTrailingComma*/ false);
8183        }
8184
8185        function parseNameOfClassDeclarationOrExpression(): Identifier | undefined {
8186            // implements is a future reserved word so
8187            // 'class implements' might mean either
8188            // - class expression with omitted name, 'implements' starts heritage clause
8189            // - class with name 'implements'
8190            // 'isImplementsClause' helps to disambiguate between these two cases
8191            return isBindingIdentifier() && !isImplementsClause()
8192                ? createIdentifier(isBindingIdentifier())
8193                : undefined;
8194        }
8195
8196        function isImplementsClause() {
8197            return token() === SyntaxKind.ImplementsKeyword && lookAhead(nextTokenIsIdentifierOrKeyword);
8198        }
8199
8200        function parseHeritageClauses(): NodeArray<HeritageClause> | undefined {
8201            // ClassTail[Yield,Await] : (Modified) See 14.5
8202            //      ClassHeritage[?Yield,?Await]opt { ClassBody[?Yield,?Await]opt }
8203
8204            if (isHeritageClause()) {
8205                return parseList(ParsingContext.HeritageClauses, parseHeritageClause);
8206            }
8207
8208            return undefined;
8209        }
8210
8211        function parseHeritageClause(): HeritageClause {
8212            const pos = getNodePos();
8213            const tok = token();
8214            Debug.assert(tok === SyntaxKind.ExtendsKeyword || tok === SyntaxKind.ImplementsKeyword); // isListElement() should ensure this.
8215            nextToken();
8216            const types = parseDelimitedList(ParsingContext.HeritageClauseElement, parseExpressionWithTypeArguments);
8217            return finishNode(factory.createHeritageClause(tok, types), pos);
8218        }
8219
8220        function parseExpressionWithTypeArguments(): ExpressionWithTypeArguments {
8221            const pos = getNodePos();
8222            const expression = parseLeftHandSideExpressionOrHigher();
8223            if (expression.kind === SyntaxKind.ExpressionWithTypeArguments) {
8224                return expression as ExpressionWithTypeArguments;
8225            }
8226            const typeArguments = tryParseTypeArguments();
8227            return finishNode(factory.createExpressionWithTypeArguments(expression, typeArguments), pos);
8228        }
8229
8230        function tryParseTypeArguments(): NodeArray<TypeNode> | undefined {
8231            return token() === SyntaxKind.LessThanToken ?
8232                parseBracketedList(ParsingContext.TypeArguments, parseType, SyntaxKind.LessThanToken, SyntaxKind.GreaterThanToken) : undefined;
8233        }
8234
8235        function isHeritageClause(): boolean {
8236            return token() === SyntaxKind.ExtendsKeyword || token() === SyntaxKind.ImplementsKeyword;
8237        }
8238
8239        function parseClassMembers(): NodeArray<ClassElement> {
8240            return parseList(ParsingContext.ClassMembers, parseClassElement);
8241        }
8242
8243        function parseAnnotationMembers(): NodeArray<AnnotationElement> {
8244            return parseList(ParsingContext.AnnotationMembers, parseAnnotationElement);
8245        }
8246
8247        function parseStructMembers(pos: number): NodeArray<ClassElement> {
8248            const structMembers = parseList(ParsingContext.ClassMembers, parseClassElement);
8249
8250            const virtualStructMembers: ClassElement[] = [];
8251            // create constructor function argument object properties
8252            const virtualParameterProperties: TypeElement[] = [];
8253            structMembers.forEach(member => {
8254                virtualStructMembers.push(member);
8255                if (member.kind === SyntaxKind.PropertyDeclaration) {
8256                    const property = <PropertyDeclaration>member;
8257                    virtualParameterProperties.push(
8258                        finishVirtualNode(
8259                            factory.createPropertySignature(getModifiers(property), property.name, factory.createToken(SyntaxKind.QuestionToken), property.type)
8260                        )
8261                    );
8262                }
8263            });
8264            const parameters: ParameterDeclaration[] = [];
8265            if (virtualParameterProperties.length) {
8266                const type = finishVirtualNode(factory.createTypeLiteralNode(createNodeArray(virtualParameterProperties, 0, 0)));
8267                parameters.push(
8268                    finishVirtualNode(
8269                        factory.createParameterDeclaration(/*modifiers*/ undefined, /*dotDotDotToken*/ undefined,
8270                            finishVirtualNode(factory.createIdentifier("value")), factory.createToken(SyntaxKind.QuestionToken), type
8271                        )
8272                    )
8273                );
8274            }
8275            // Add parameter ##storage?: LocalStorage to struct constructor.
8276            parameters.push(
8277                finishVirtualNode(
8278                    factory.createParameterDeclaration(/*modifiers*/ undefined, /*dotDotDotToken*/ undefined,
8279                        finishVirtualNode(factory.createIdentifier("##storage")), factory.createToken(SyntaxKind.QuestionToken),
8280                        finishVirtualNode(factory.createTypeReferenceNode(finishVirtualNode(factory.createIdentifier("LocalStorage"))))
8281                    )
8282                )
8283            );
8284            const emptyBody = finishVirtualNode(factory.createBlock(createNodeArray([], 0, 0)));
8285            const virtualConstructor = factory.createConstructorDeclaration(/*modifier*/ undefined, createNodeArray(parameters, 0, 0), emptyBody);
8286
8287            virtualStructMembers.unshift(finishVirtualNode(virtualConstructor, pos, pos));
8288
8289            return createNodeArray(virtualStructMembers, structMembers.pos);
8290        }
8291
8292        function finishVirtualNode<T extends Node>(node: T, start = 0, end = 0) {
8293            return finishNode(node, start, end, /*virtual*/ true);
8294        }
8295
8296        function parseInterfaceDeclaration(pos: number, hasJSDoc: boolean, decorators: NodeArray<Decorator> | undefined, modifiers: NodeArray<Modifier> | undefined): InterfaceDeclaration {
8297            parseExpected(SyntaxKind.InterfaceKeyword);
8298            const name = parseIdentifier();
8299            const typeParameters = parseTypeParameters();
8300            const heritageClauses = parseHeritageClauses();
8301            const members = parseObjectTypeMembers();
8302            const node = factory.createInterfaceDeclaration(modifiers, name, typeParameters, heritageClauses, members);
8303            (node as Mutable<InterfaceDeclaration>).illegalDecorators = decorators;
8304            return withJSDoc(finishNode(node, pos), hasJSDoc);
8305        }
8306
8307        function parseTypeAliasDeclaration(pos: number, hasJSDoc: boolean, decorators: NodeArray<Decorator> | undefined, modifiers: NodeArray<Modifier> | undefined): TypeAliasDeclaration {
8308            parseExpected(SyntaxKind.TypeKeyword);
8309            const name = parseIdentifier();
8310            const typeParameters = parseTypeParameters();
8311            parseExpected(SyntaxKind.EqualsToken);
8312            const type = token() === SyntaxKind.IntrinsicKeyword && tryParse(parseKeywordAndNoDot) || parseType();
8313            parseSemicolon();
8314            const node = factory.createTypeAliasDeclaration(modifiers, name, typeParameters, type);
8315            (node as Mutable<TypeAliasDeclaration>).illegalDecorators = decorators;
8316            return withJSDoc(finishNode(node, pos), hasJSDoc);
8317        }
8318
8319        // In an ambient declaration, the grammar only allows integer literals as initializers.
8320        // In a non-ambient declaration, the grammar allows uninitialized members only in a
8321        // ConstantEnumMemberSection, which starts at the beginning of an enum declaration
8322        // or any time an integer literal initializer is encountered.
8323        function parseEnumMember(): EnumMember {
8324            const pos = getNodePos();
8325            const hasJSDoc = hasPrecedingJSDocComment();
8326            const name = parsePropertyName();
8327            const initializer = allowInAnd(parseInitializer);
8328            return withJSDoc(finishNode(factory.createEnumMember(name, initializer), pos), hasJSDoc);
8329        }
8330
8331        function parseEnumDeclaration(pos: number, hasJSDoc: boolean, decorators: NodeArray<Decorator> | undefined, modifiers: NodeArray<Modifier> | undefined): EnumDeclaration {
8332            parseExpected(SyntaxKind.EnumKeyword);
8333            const name = parseIdentifier();
8334            let members;
8335            if (parseExpected(SyntaxKind.OpenBraceToken)) {
8336                members = doOutsideOfYieldAndAwaitContext(() => parseDelimitedList(ParsingContext.EnumMembers, parseEnumMember));
8337                parseExpected(SyntaxKind.CloseBraceToken);
8338            }
8339            else {
8340                members = createMissingList<EnumMember>();
8341            }
8342            const node = factory.createEnumDeclaration(modifiers, name, members);
8343            (node as Mutable<EnumDeclaration>).illegalDecorators = decorators;
8344            return withJSDoc(finishNode(node, pos), hasJSDoc);
8345        }
8346
8347        function parseModuleBlock(): ModuleBlock {
8348            const pos = getNodePos();
8349            let statements;
8350            if (parseExpected(SyntaxKind.OpenBraceToken)) {
8351                statements = parseList(ParsingContext.BlockStatements, parseStatement);
8352                parseExpected(SyntaxKind.CloseBraceToken);
8353            }
8354            else {
8355                statements = createMissingList<Statement>();
8356            }
8357            return finishNode(factory.createModuleBlock(statements), pos);
8358        }
8359
8360        function parseModuleOrNamespaceDeclaration(pos: number, hasJSDoc: boolean, decorators: NodeArray<Decorator> | undefined, modifiers: NodeArray<Modifier> | undefined, flags: NodeFlags): ModuleDeclaration {
8361            // If we are parsing a dotted namespace name, we want to
8362            // propagate the 'Namespace' flag across the names if set.
8363            const namespaceFlag = flags & NodeFlags.Namespace;
8364            const name = parseIdentifier();
8365            const body = parseOptional(SyntaxKind.DotToken)
8366                ? parseModuleOrNamespaceDeclaration(getNodePos(), /*hasJSDoc*/ false, /*decorators*/ undefined, /*modifiers*/ undefined, NodeFlags.NestedNamespace | namespaceFlag) as NamespaceDeclaration
8367                : parseModuleBlock();
8368            const node = factory.createModuleDeclaration(modifiers, name, body, flags);
8369            (node as Mutable<ModuleDeclaration>).illegalDecorators = decorators;
8370            return withJSDoc(finishNode(node, pos), hasJSDoc);
8371        }
8372
8373        function parseAmbientExternalModuleDeclaration(pos: number, hasJSDoc: boolean, decorators: NodeArray<Decorator> | undefined, modifiers: NodeArray<Modifier> | undefined): ModuleDeclaration {
8374            let flags: NodeFlags = 0;
8375            let name;
8376            if (token() === SyntaxKind.GlobalKeyword) {
8377                // parse 'global' as name of global scope augmentation
8378                name = parseIdentifier();
8379                flags |= NodeFlags.GlobalAugmentation;
8380            }
8381            else {
8382                name = parseLiteralNode() as StringLiteral;
8383                name.text = internIdentifier(name.text);
8384            }
8385            let body: ModuleBlock | undefined;
8386            if (token() === SyntaxKind.OpenBraceToken) {
8387                body = parseModuleBlock();
8388            }
8389            else {
8390                parseSemicolon();
8391            }
8392            const node = factory.createModuleDeclaration(modifiers, name, body, flags);
8393            (node as Mutable<ModuleDeclaration>).illegalDecorators = decorators;
8394            return withJSDoc(finishNode(node, pos), hasJSDoc);
8395        }
8396
8397        function parseModuleDeclaration(pos: number, hasJSDoc: boolean, decorators: NodeArray<Decorator> | undefined, modifiers: NodeArray<Modifier> | undefined): ModuleDeclaration {
8398            let flags: NodeFlags = 0;
8399            if (token() === SyntaxKind.GlobalKeyword) {
8400                // global augmentation
8401                return parseAmbientExternalModuleDeclaration(pos, hasJSDoc, decorators, modifiers);
8402            }
8403            else if (parseOptional(SyntaxKind.NamespaceKeyword)) {
8404                flags |= NodeFlags.Namespace;
8405            }
8406            else {
8407                parseExpected(SyntaxKind.ModuleKeyword);
8408                if (token() === SyntaxKind.StringLiteral) {
8409                    return parseAmbientExternalModuleDeclaration(pos, hasJSDoc, decorators, modifiers);
8410                }
8411            }
8412            return parseModuleOrNamespaceDeclaration(pos, hasJSDoc, decorators, modifiers, flags);
8413        }
8414
8415        function isExternalModuleReference() {
8416            return token() === SyntaxKind.RequireKeyword &&
8417                lookAhead(nextTokenIsOpenParen);
8418        }
8419
8420        function nextTokenIsOpenParen() {
8421            return nextToken() === SyntaxKind.OpenParenToken;
8422        }
8423
8424        function nextTokenIsOpenBrace() {
8425            return nextToken() === SyntaxKind.OpenBraceToken;
8426        }
8427
8428        function nextTokenIsSlash() {
8429            return nextToken() === SyntaxKind.SlashToken;
8430        }
8431
8432        function parseNamespaceExportDeclaration(pos: number, hasJSDoc: boolean, decorators: NodeArray<Decorator> | undefined, modifiers: NodeArray<Modifier> | undefined): NamespaceExportDeclaration {
8433            parseExpected(SyntaxKind.AsKeyword);
8434            parseExpected(SyntaxKind.NamespaceKeyword);
8435            const name = parseIdentifier();
8436            parseSemicolon();
8437            const node = factory.createNamespaceExportDeclaration(name);
8438            // NamespaceExportDeclaration nodes cannot have decorators or modifiers, so we attach them here so we can report them in the grammar checker
8439            (node as Mutable<NamespaceExportDeclaration>).illegalDecorators = decorators;
8440            (node as Mutable<NamespaceExportDeclaration>).modifiers = modifiers;
8441            return withJSDoc(finishNode(node, pos), hasJSDoc);
8442        }
8443
8444        function parseImportDeclarationOrImportEqualsDeclaration(pos: number, hasJSDoc: boolean, decorators: NodeArray<Decorator> | undefined, modifiers: NodeArray<Modifier> | undefined): ImportEqualsDeclaration | ImportDeclaration {
8445            parseExpected(SyntaxKind.ImportKeyword);
8446
8447            const afterImportPos = scanner.getStartPos();
8448
8449            // We don't parse the identifier here in await context, instead we will report a grammar error in the checker.
8450            let identifier: Identifier | undefined;
8451            if (isIdentifier()) {
8452                identifier = parseIdentifier();
8453            }
8454
8455            let isTypeOnly = false;
8456            let isLazy = false;
8457            if (token() !== SyntaxKind.FromKeyword &&
8458                identifier?.escapedText === "type" &&
8459                (isIdentifier() || tokenAfterImportDefinitelyProducesImportDeclaration())
8460            ) {
8461                isTypeOnly = true;
8462                identifier = isIdentifier() ? parseIdentifier() : undefined;
8463            }
8464            else if (isSetLazy(identifier)) {
8465                isLazy = true;
8466                identifier = isIdentifier() ? parseIdentifier() : undefined;
8467            }
8468
8469            if (identifier && !tokenAfterImportedIdentifierDefinitelyProducesImportDeclaration()) {
8470                return parseImportEqualsDeclaration(pos, hasJSDoc, decorators, modifiers, identifier, isTypeOnly);
8471            }
8472
8473            // ImportDeclaration:
8474            //  import ImportClause from ModuleSpecifier;
8475            //  import ModuleSpecifier;
8476            let importClause: ImportClause | undefined;
8477            if (identifier || // import id
8478                token() === SyntaxKind.AsteriskToken || // import *
8479                token() === SyntaxKind.OpenBraceToken    // import {
8480            ) {
8481                importClause = parseImportClause(identifier, afterImportPos, isTypeOnly);
8482                (importClause as Mutable<ImportClause>).isLazy = isLazy;
8483                parseExpected(SyntaxKind.FromKeyword);
8484            }
8485            const moduleSpecifier = parseModuleSpecifier();
8486
8487            let assertClause: AssertClause | undefined;
8488            if (token() === SyntaxKind.AssertKeyword && !scanner.hasPrecedingLineBreak()) {
8489                assertClause = parseAssertClause();
8490            }
8491
8492            parseSemicolon();
8493            const node = factory.createImportDeclaration(modifiers, importClause, moduleSpecifier, assertClause);
8494            (node as Mutable<ImportDeclaration>).illegalDecorators = decorators;
8495            return withJSDoc(finishNode(node, pos), hasJSDoc);
8496        }
8497
8498        function isSetLazy(identifier: Identifier | undefined): boolean {
8499            // 1. import lazy { export } from "mod";
8500            // 2. import lazy defaultExport from "mod";
8501            // 3. import lazy defaultExport, { export, /* ... */ } from "mod";
8502            return identifier?.escapedText === 'lazy' &&
8503                (token() === SyntaxKind.OpenBraceToken ||
8504                (isIdentifier() && lookAhead(() => nextToken() === SyntaxKind.FromKeyword)) ||
8505                (isIdentifier() && lookAhead(() => nextToken() === SyntaxKind.CommaToken && nextToken() === SyntaxKind.OpenBraceToken)));
8506        }
8507
8508        function parseAssertEntry() {
8509            const pos = getNodePos();
8510            const name = tokenIsIdentifierOrKeyword(token()) ? parseIdentifierName() : parseLiteralLikeNode(SyntaxKind.StringLiteral) as StringLiteral;
8511            parseExpected(SyntaxKind.ColonToken);
8512            const value = parseAssignmentExpressionOrHigher(/*allowReturnTypeInArrowFunction*/ true);
8513            return finishNode(factory.createAssertEntry(name, value), pos);
8514        }
8515
8516        function parseAssertClause(skipAssertKeyword?: true) {
8517            const pos = getNodePos();
8518            if (!skipAssertKeyword) {
8519                parseExpected(SyntaxKind.AssertKeyword);
8520            }
8521            const openBracePosition = scanner.getTokenPos();
8522            if (parseExpected(SyntaxKind.OpenBraceToken)) {
8523                const multiLine = scanner.hasPrecedingLineBreak();
8524                const elements = parseDelimitedList(ParsingContext.AssertEntries, parseAssertEntry, /*considerSemicolonAsDelimiter*/ true);
8525                if (!parseExpected(SyntaxKind.CloseBraceToken)) {
8526                    const lastError = lastOrUndefined(parseDiagnostics);
8527                    if (lastError && lastError.code === Diagnostics._0_expected.code) {
8528                        addRelatedInfo(
8529                            lastError,
8530                            createDetachedDiagnostic(fileName, openBracePosition, 1, Diagnostics.The_parser_expected_to_find_a_1_to_match_the_0_token_here, "{", "}")
8531                        );
8532                    }
8533                }
8534                return finishNode(factory.createAssertClause(elements, multiLine), pos);
8535            }
8536            else {
8537                const elements = createNodeArray([], getNodePos(), /*end*/ undefined, /*hasTrailingComma*/ false);
8538                return finishNode(factory.createAssertClause(elements, /*multiLine*/ false), pos);
8539            }
8540        }
8541
8542        function tokenAfterImportDefinitelyProducesImportDeclaration() {
8543            return token() === SyntaxKind.AsteriskToken || token() === SyntaxKind.OpenBraceToken;
8544        }
8545
8546        function tokenAfterImportedIdentifierDefinitelyProducesImportDeclaration() {
8547            // In `import id ___`, the current token decides whether to produce
8548            // an ImportDeclaration or ImportEqualsDeclaration.
8549            return token() === SyntaxKind.CommaToken || token() === SyntaxKind.FromKeyword;
8550        }
8551
8552        function parseImportEqualsDeclaration(pos: number, hasJSDoc: boolean, decorators: NodeArray<Decorator> | undefined, modifiers: NodeArray<Modifier> | undefined, identifier: Identifier, isTypeOnly: boolean): ImportEqualsDeclaration {
8553            parseExpected(SyntaxKind.EqualsToken);
8554            const moduleReference = parseModuleReference();
8555            parseSemicolon();
8556            const node = factory.createImportEqualsDeclaration(modifiers, isTypeOnly, identifier, moduleReference);
8557            (node as Mutable<ImportEqualsDeclaration>).illegalDecorators = decorators;
8558            const finished = withJSDoc(finishNode(node, pos), hasJSDoc);
8559            return finished;
8560        }
8561
8562        function parseImportClause(identifier: Identifier | undefined, pos: number, isTypeOnly: boolean) {
8563            // ImportClause:
8564            //  ImportedDefaultBinding
8565            //  NameSpaceImport
8566            //  NamedImports
8567            //  ImportedDefaultBinding, NameSpaceImport
8568            //  ImportedDefaultBinding, NamedImports
8569
8570            // If there was no default import or if there is comma token after default import
8571            // parse namespace or named imports
8572            let namedBindings: NamespaceImport | NamedImports | undefined;
8573            if (!identifier ||
8574                parseOptional(SyntaxKind.CommaToken)) {
8575                namedBindings = token() === SyntaxKind.AsteriskToken ? parseNamespaceImport() : parseNamedImportsOrExports(SyntaxKind.NamedImports);
8576            }
8577
8578            return finishNode(factory.createImportClause(isTypeOnly, identifier, namedBindings), pos);
8579        }
8580
8581        function parseModuleReference() {
8582            return isExternalModuleReference()
8583                ? parseExternalModuleReference()
8584                : parseEntityName(/*allowReservedWords*/ false);
8585        }
8586
8587        function parseExternalModuleReference() {
8588            const pos = getNodePos();
8589            parseExpected(SyntaxKind.RequireKeyword);
8590            parseExpected(SyntaxKind.OpenParenToken);
8591            const expression = parseModuleSpecifier();
8592            parseExpected(SyntaxKind.CloseParenToken);
8593            return finishNode(factory.createExternalModuleReference(expression), pos);
8594        }
8595
8596        function parseModuleSpecifier(): Expression {
8597            if (token() === SyntaxKind.StringLiteral) {
8598                const result = parseLiteralNode();
8599                result.text = internIdentifier(result.text);
8600                return result;
8601            }
8602            else {
8603                // We allow arbitrary expressions here, even though the grammar only allows string
8604                // literals.  We check to ensure that it is only a string literal later in the grammar
8605                // check pass.
8606                return parseExpression();
8607            }
8608        }
8609
8610        function parseNamespaceImport(): NamespaceImport {
8611            // NameSpaceImport:
8612            //  * as ImportedBinding
8613            const pos = getNodePos();
8614            parseExpected(SyntaxKind.AsteriskToken);
8615            parseExpected(SyntaxKind.AsKeyword);
8616            const name = parseIdentifier();
8617            return finishNode(factory.createNamespaceImport(name), pos);
8618        }
8619
8620        function parseNamedImportsOrExports(kind: SyntaxKind.NamedImports): NamedImports;
8621        function parseNamedImportsOrExports(kind: SyntaxKind.NamedExports): NamedExports;
8622        function parseNamedImportsOrExports(kind: SyntaxKind): NamedImportsOrExports {
8623            const pos = getNodePos();
8624
8625            // NamedImports:
8626            //  { }
8627            //  { ImportsList }
8628            //  { ImportsList, }
8629
8630            // ImportsList:
8631            //  ImportSpecifier
8632            //  ImportsList, ImportSpecifier
8633            const node = kind === SyntaxKind.NamedImports
8634                ? factory.createNamedImports(parseBracketedList(ParsingContext.ImportOrExportSpecifiers, parseImportSpecifier, SyntaxKind.OpenBraceToken, SyntaxKind.CloseBraceToken))
8635                : factory.createNamedExports(parseBracketedList(ParsingContext.ImportOrExportSpecifiers, parseExportSpecifier, SyntaxKind.OpenBraceToken, SyntaxKind.CloseBraceToken));
8636            return finishNode(node, pos);
8637        }
8638
8639        function parseExportSpecifier() {
8640            const hasJSDoc = hasPrecedingJSDocComment();
8641            return withJSDoc(parseImportOrExportSpecifier(SyntaxKind.ExportSpecifier) as ExportSpecifier, hasJSDoc);
8642        }
8643
8644        function parseImportSpecifier() {
8645            return parseImportOrExportSpecifier(SyntaxKind.ImportSpecifier) as ImportSpecifier;
8646        }
8647
8648        function parseImportOrExportSpecifier(kind: SyntaxKind): ImportOrExportSpecifier {
8649            const pos = getNodePos();
8650            // ImportSpecifier:
8651            //   BindingIdentifier
8652            //   IdentifierName as BindingIdentifier
8653            // ExportSpecifier:
8654            //   IdentifierName
8655            //   IdentifierName as IdentifierName
8656            let checkIdentifierIsKeyword = isKeyword(token()) && !isIdentifier();
8657            let checkIdentifierStart = scanner.getTokenPos();
8658            let checkIdentifierEnd = scanner.getTextPos();
8659            let isTypeOnly = false;
8660            let propertyName: Identifier | undefined;
8661            let canParseAsKeyword = true;
8662            let name = parseIdentifierName();
8663            if (name.escapedText === "type") {
8664                // If the first token of an import specifier is 'type', there are a lot of possibilities,
8665                // especially if we see 'as' afterwards:
8666                //
8667                // import { type } from "mod";          - isTypeOnly: false,   name: type
8668                // import { type as } from "mod";       - isTypeOnly: true,    name: as
8669                // import { type as as } from "mod";    - isTypeOnly: false,   name: as,    propertyName: type
8670                // import { type as as as } from "mod"; - isTypeOnly: true,    name: as,    propertyName: as
8671                if (token() === SyntaxKind.AsKeyword) {
8672                    // { type as ...? }
8673                    const firstAs = parseIdentifierName();
8674                    if (token() === SyntaxKind.AsKeyword) {
8675                        // { type as as ...? }
8676                        const secondAs = parseIdentifierName();
8677                        if (tokenIsIdentifierOrKeyword(token())) {
8678                            // { type as as something }
8679                            isTypeOnly = true;
8680                            propertyName = firstAs;
8681                            name = parseNameWithKeywordCheck();
8682                            canParseAsKeyword = false;
8683                        }
8684                        else {
8685                            // { type as as }
8686                            propertyName = name;
8687                            name = secondAs;
8688                            canParseAsKeyword = false;
8689                        }
8690                    }
8691                    else if (tokenIsIdentifierOrKeyword(token())) {
8692                        // { type as something }
8693                        propertyName = name;
8694                        canParseAsKeyword = false;
8695                        name = parseNameWithKeywordCheck();
8696                    }
8697                    else {
8698                        // { type as }
8699                        isTypeOnly = true;
8700                        name = firstAs;
8701                    }
8702                }
8703                else if (tokenIsIdentifierOrKeyword(token())) {
8704                    // { type something ...? }
8705                    isTypeOnly = true;
8706                    name = parseNameWithKeywordCheck();
8707                }
8708            }
8709
8710            if (canParseAsKeyword && token() === SyntaxKind.AsKeyword) {
8711                propertyName = name;
8712                parseExpected(SyntaxKind.AsKeyword);
8713                name = parseNameWithKeywordCheck();
8714            }
8715            if (kind === SyntaxKind.ImportSpecifier && checkIdentifierIsKeyword) {
8716                parseErrorAt(checkIdentifierStart, checkIdentifierEnd, Diagnostics.Identifier_expected);
8717            }
8718            const node = kind === SyntaxKind.ImportSpecifier
8719                ? factory.createImportSpecifier(isTypeOnly, propertyName, name)
8720                : factory.createExportSpecifier(isTypeOnly, propertyName, name);
8721            return finishNode(node, pos);
8722
8723            function parseNameWithKeywordCheck() {
8724                checkIdentifierIsKeyword = isKeyword(token()) && !isIdentifier();
8725                checkIdentifierStart = scanner.getTokenPos();
8726                checkIdentifierEnd = scanner.getTextPos();
8727                return parseIdentifierName();
8728            }
8729        }
8730
8731        function parseNamespaceExport(pos: number): NamespaceExport {
8732            return finishNode(factory.createNamespaceExport(parseIdentifierName()), pos);
8733        }
8734
8735        function parseExportDeclaration(pos: number, hasJSDoc: boolean, decorators: NodeArray<Decorator> | undefined, modifiers: NodeArray<Modifier> | undefined): ExportDeclaration {
8736            const savedAwaitContext = inAwaitContext();
8737            setAwaitContext(/*value*/ true);
8738            let exportClause: NamedExportBindings | undefined;
8739            let moduleSpecifier: Expression | undefined;
8740            let assertClause: AssertClause | undefined;
8741            const isTypeOnly = parseOptional(SyntaxKind.TypeKeyword);
8742            const namespaceExportPos = getNodePos();
8743            if (parseOptional(SyntaxKind.AsteriskToken)) {
8744                if (parseOptional(SyntaxKind.AsKeyword)) {
8745                    exportClause = parseNamespaceExport(namespaceExportPos);
8746                }
8747                parseExpected(SyntaxKind.FromKeyword);
8748                moduleSpecifier = parseModuleSpecifier();
8749            }
8750            else {
8751                exportClause = parseNamedImportsOrExports(SyntaxKind.NamedExports);
8752                // It is not uncommon to accidentally omit the 'from' keyword. Additionally, in editing scenarios,
8753                // the 'from' keyword can be parsed as a named export when the export clause is unterminated (i.e. `export { from "moduleName";`)
8754                // If we don't have a 'from' keyword, see if we have a string literal such that ASI won't take effect.
8755                if (token() === SyntaxKind.FromKeyword || (token() === SyntaxKind.StringLiteral && !scanner.hasPrecedingLineBreak())) {
8756                    parseExpected(SyntaxKind.FromKeyword);
8757                    moduleSpecifier = parseModuleSpecifier();
8758                }
8759            }
8760            if (moduleSpecifier && token() === SyntaxKind.AssertKeyword && !scanner.hasPrecedingLineBreak()) {
8761                assertClause = parseAssertClause();
8762            }
8763            parseSemicolon();
8764            setAwaitContext(savedAwaitContext);
8765            const node = factory.createExportDeclaration(modifiers, isTypeOnly, exportClause, moduleSpecifier, assertClause);
8766            (node as Mutable<ExportDeclaration>).illegalDecorators = decorators;
8767            return withJSDoc(finishNode(node, pos), hasJSDoc);
8768        }
8769
8770        function parseExportAssignment(pos: number, hasJSDoc: boolean, decorators: NodeArray<Decorator> | undefined, modifiers: NodeArray<Modifier> | undefined): ExportAssignment {
8771            const savedAwaitContext = inAwaitContext();
8772            setAwaitContext(/*value*/ true);
8773            let isExportEquals: boolean | undefined;
8774            if (parseOptional(SyntaxKind.EqualsToken)) {
8775                isExportEquals = true;
8776            }
8777            else {
8778                parseExpected(SyntaxKind.DefaultKeyword);
8779            }
8780            const expression = parseAssignmentExpressionOrHigher(/*allowReturnTypeInArrowFunction*/ true);
8781            parseSemicolon();
8782            setAwaitContext(savedAwaitContext);
8783            const node = factory.createExportAssignment(modifiers, isExportEquals, expression);
8784            (node as Mutable<ExportAssignment>).illegalDecorators = decorators;
8785            return withJSDoc(finishNode(node, pos), hasJSDoc);
8786        }
8787
8788        const enum ParsingContext {
8789            SourceElements,            // Elements in source file
8790            BlockStatements,           // Statements in block
8791            SwitchClauses,             // Clauses in switch statement
8792            SwitchClauseStatements,    // Statements in switch clause
8793            TypeMembers,               // Members in interface or type literal
8794            ClassMembers,              // Members in class declaration
8795            AnnotationMembers,         // Members in annotation declaration
8796            EnumMembers,               // Members in enum declaration
8797            HeritageClauseElement,     // Elements in a heritage clause
8798            VariableDeclarations,      // Variable declarations in variable statement
8799            ObjectBindingElements,     // Binding elements in object binding list
8800            ArrayBindingElements,      // Binding elements in array binding list
8801            ArgumentExpressions,       // Expressions in argument list
8802            ObjectLiteralMembers,      // Members in object literal
8803            JsxAttributes,             // Attributes in jsx element
8804            JsxChildren,               // Things between opening and closing JSX tags
8805            ArrayLiteralMembers,       // Members in array literal
8806            Parameters,                // Parameters in parameter list
8807            JSDocParameters,           // JSDoc parameters in parameter list of JSDoc function type
8808            RestProperties,            // Property names in a rest type list
8809            TypeParameters,            // Type parameters in type parameter list
8810            TypeArguments,             // Type arguments in type argument list
8811            TupleElementTypes,         // Element types in tuple element type list
8812            HeritageClauses,           // Heritage clauses for a class or interface declaration.
8813            ImportOrExportSpecifiers,  // Named import clause's import specifier list,
8814            AssertEntries,               // Import entries list.
8815            Count                      // Number of parsing contexts
8816        }
8817
8818        const enum Tristate {
8819            False,
8820            True,
8821            Unknown
8822        }
8823
8824        export namespace JSDocParser {
8825            export function parseJSDocTypeExpressionForTests(content: string, start: number | undefined, length: number | undefined): { jsDocTypeExpression: JSDocTypeExpression, diagnostics: Diagnostic[] } | undefined {
8826                initializeState("file.js", content, ScriptTarget.Latest, /*_syntaxCursor:*/ undefined, ScriptKind.JS);
8827                scanner.setText(content, start, length);
8828                currentToken = scanner.scan();
8829                const jsDocTypeExpression = parseJSDocTypeExpression();
8830
8831                const sourceFile = createSourceFile("file.js", ScriptTarget.Latest, ScriptKind.JS, /*isDeclarationFile*/ false, [], factory.createToken(SyntaxKind.EndOfFileToken), NodeFlags.None, noop);
8832                const diagnostics = attachFileToDiagnostics(parseDiagnostics, sourceFile);
8833                if (jsDocDiagnostics) {
8834                    sourceFile.jsDocDiagnostics = attachFileToDiagnostics(jsDocDiagnostics, sourceFile);
8835                }
8836
8837                clearState();
8838
8839                return jsDocTypeExpression ? { jsDocTypeExpression, diagnostics } : undefined;
8840            }
8841
8842            // Parses out a JSDoc type expression.
8843            export function parseJSDocTypeExpression(mayOmitBraces?: boolean): JSDocTypeExpression {
8844                const pos = getNodePos();
8845                const hasBrace = (mayOmitBraces ? parseOptional : parseExpected)(SyntaxKind.OpenBraceToken);
8846                const type = doInsideOfContext(NodeFlags.JSDoc, parseJSDocType);
8847                if (!mayOmitBraces || hasBrace) {
8848                    parseExpectedJSDoc(SyntaxKind.CloseBraceToken);
8849                }
8850
8851                const result = factory.createJSDocTypeExpression(type);
8852                fixupParentReferences(result);
8853                return finishNode(result, pos);
8854            }
8855
8856            export function parseJSDocNameReference(): JSDocNameReference {
8857                const pos = getNodePos();
8858                const hasBrace = parseOptional(SyntaxKind.OpenBraceToken);
8859                const p2 = getNodePos();
8860                let entityName: EntityName | JSDocMemberName = parseEntityName(/* allowReservedWords*/ false);
8861                while (token() === SyntaxKind.PrivateIdentifier) {
8862                    reScanHashToken(); // rescan #id as # id
8863                    nextTokenJSDoc(); // then skip the #
8864                    entityName = finishNode(factory.createJSDocMemberName(entityName, parseIdentifier()), p2);
8865                }
8866                if (hasBrace) {
8867                    parseExpectedJSDoc(SyntaxKind.CloseBraceToken);
8868                }
8869
8870                const result = factory.createJSDocNameReference(entityName);
8871                fixupParentReferences(result);
8872                return finishNode(result, pos);
8873            }
8874
8875            export function parseIsolatedJSDocComment(content: string, start: number | undefined, length: number | undefined): { jsDoc: JSDoc, diagnostics: Diagnostic[] } | undefined {
8876                initializeState("", content, ScriptTarget.Latest, /*_syntaxCursor:*/ undefined, ScriptKind.JS);
8877                const jsDoc = doInsideOfContext(NodeFlags.JSDoc, () => parseJSDocCommentWorker(start, length));
8878
8879                const sourceFile = { languageVariant: LanguageVariant.Standard, text: content } as SourceFile;
8880                const diagnostics = attachFileToDiagnostics(parseDiagnostics, sourceFile);
8881                clearState();
8882
8883                return jsDoc ? { jsDoc, diagnostics } : undefined;
8884            }
8885
8886            export function parseJSDocComment(parent: HasJSDoc, start: number, length: number): JSDoc | undefined {
8887                const saveToken = currentToken;
8888                const saveParseDiagnosticsLength = parseDiagnostics.length;
8889                const saveParseErrorBeforeNextFinishedNode = parseErrorBeforeNextFinishedNode;
8890
8891                const comment = doInsideOfContext(NodeFlags.JSDoc, () => parseJSDocCommentWorker(start, length));
8892                setParent(comment, parent);
8893
8894                if (contextFlags & NodeFlags.JavaScriptFile) {
8895                    if (!jsDocDiagnostics) {
8896                        jsDocDiagnostics = [];
8897                    }
8898                    jsDocDiagnostics.push(...parseDiagnostics);
8899                }
8900                currentToken = saveToken;
8901                parseDiagnostics.length = saveParseDiagnosticsLength;
8902                parseErrorBeforeNextFinishedNode = saveParseErrorBeforeNextFinishedNode;
8903                return comment;
8904            }
8905
8906            const enum JSDocState {
8907                BeginningOfLine,
8908                SawAsterisk,
8909                SavingComments,
8910                SavingBackticks, // NOTE: Only used when parsing tag comments
8911            }
8912
8913            const enum PropertyLikeParse {
8914                Property = 1 << 0,
8915                Parameter = 1 << 1,
8916                CallbackParameter = 1 << 2,
8917            }
8918
8919            function parseJSDocCommentWorker(start = 0, length: number | undefined): JSDoc | undefined {
8920                const content = sourceText;
8921                const end = length === undefined ? content.length : start + length;
8922                length = end - start;
8923
8924                Debug.assert(start >= 0);
8925                Debug.assert(start <= end);
8926                Debug.assert(end <= content.length);
8927
8928                // Check for /** (JSDoc opening part)
8929                if (!isJSDocLikeText(content, start)) {
8930                    return undefined;
8931                }
8932
8933                let tags: JSDocTag[];
8934                let tagsPos: number;
8935                let tagsEnd: number;
8936                let linkEnd: number;
8937                let commentsPos: number | undefined;
8938                let comments: string[] = [];
8939                const parts: JSDocComment[] = [];
8940
8941                // + 3 for leading /**, - 5 in total for /** */
8942                return scanner.scanRange(start + 3, length - 5, () => {
8943                    // Initially we can parse out a tag.  We also have seen a starting asterisk.
8944                    // This is so that /** * @type */ doesn't parse.
8945                    let state = JSDocState.SawAsterisk;
8946                    let margin: number | undefined;
8947                    // + 4 for leading '/** '
8948                    // + 1 because the last index of \n is always one index before the first character in the line and coincidentally, if there is no \n before start, it is -1, which is also one index before the first character
8949                    let indent = start - (content.lastIndexOf("\n", start) + 1) + 4;
8950                    function pushComment(text: string) {
8951                        if (!margin) {
8952                            margin = indent;
8953                        }
8954                        comments.push(text);
8955                        indent += text.length;
8956                    }
8957
8958                    nextTokenJSDoc();
8959                    while (parseOptionalJsdoc(SyntaxKind.WhitespaceTrivia));
8960                    if (parseOptionalJsdoc(SyntaxKind.NewLineTrivia)) {
8961                        state = JSDocState.BeginningOfLine;
8962                        indent = 0;
8963                    }
8964                    loop: while (true) {
8965                        switch (token()) {
8966                            case SyntaxKind.AtToken:
8967                                if (state === JSDocState.BeginningOfLine || state === JSDocState.SawAsterisk) {
8968                                    removeTrailingWhitespace(comments);
8969                                    if (!commentsPos) commentsPos = getNodePos();
8970                                    addTag(parseTag(indent));
8971                                    // NOTE: According to usejsdoc.org, a tag goes to end of line, except the last tag.
8972                                    // Real-world comments may break this rule, so "BeginningOfLine" will not be a real line beginning
8973                                    // for malformed examples like `/** @param {string} x @returns {number} the length */`
8974                                    state = JSDocState.BeginningOfLine;
8975                                    margin = undefined;
8976                                }
8977                                else {
8978                                    pushComment(scanner.getTokenText());
8979                                }
8980                                break;
8981                            case SyntaxKind.NewLineTrivia:
8982                                comments.push(scanner.getTokenText());
8983                                state = JSDocState.BeginningOfLine;
8984                                indent = 0;
8985                                break;
8986                            case SyntaxKind.AsteriskToken:
8987                                const asterisk = scanner.getTokenText();
8988                                if (state === JSDocState.SawAsterisk || state === JSDocState.SavingComments) {
8989                                    // If we've already seen an asterisk, then we can no longer parse a tag on this line
8990                                    state = JSDocState.SavingComments;
8991                                    pushComment(asterisk);
8992                                }
8993                                else {
8994                                    // Ignore the first asterisk on a line
8995                                    state = JSDocState.SawAsterisk;
8996                                    indent += asterisk.length;
8997                                }
8998                                break;
8999                            case SyntaxKind.WhitespaceTrivia:
9000                                // only collect whitespace if we're already saving comments or have just crossed the comment indent margin
9001                                const whitespace = scanner.getTokenText();
9002                                if (state === JSDocState.SavingComments) {
9003                                    comments.push(whitespace);
9004                                }
9005                                else if (margin !== undefined && indent + whitespace.length > margin) {
9006                                    comments.push(whitespace.slice(margin - indent));
9007                                }
9008                                indent += whitespace.length;
9009                                break;
9010                            case SyntaxKind.EndOfFileToken:
9011                                break loop;
9012                            case SyntaxKind.OpenBraceToken:
9013                                state = JSDocState.SavingComments;
9014                                const commentEnd = scanner.getStartPos();
9015                                const linkStart = scanner.getTextPos() - 1;
9016                                const link = parseJSDocLink(linkStart);
9017                                if (link) {
9018                                    if (!linkEnd) {
9019                                        removeLeadingNewlines(comments);
9020                                    }
9021                                    parts.push(finishNode(factory.createJSDocText(comments.join("")), linkEnd ?? start, commentEnd));
9022                                    parts.push(link);
9023                                    comments = [];
9024                                    linkEnd = scanner.getTextPos();
9025                                    break;
9026                                }
9027                                // fallthrough if it's not a {@link sequence
9028                            default:
9029                                // Anything else is doc comment text. We just save it. Because it
9030                                // wasn't a tag, we can no longer parse a tag on this line until we hit the next
9031                                // line break.
9032                                state = JSDocState.SavingComments;
9033                                pushComment(scanner.getTokenText());
9034                                break;
9035                        }
9036                        nextTokenJSDoc();
9037                    }
9038                    removeTrailingWhitespace(comments);
9039                    if (parts.length && comments.length) {
9040                        parts.push(finishNode(factory.createJSDocText(comments.join("")), linkEnd ?? start, commentsPos));
9041                    }
9042                    if (parts.length && tags) Debug.assertIsDefined(commentsPos, "having parsed tags implies that the end of the comment span should be set");
9043                    const tagsArray = tags && createNodeArray(tags, tagsPos, tagsEnd);
9044                    return finishNode(factory.createJSDocComment(parts.length ? createNodeArray(parts, start, commentsPos) : comments.length ? comments.join("") : undefined, tagsArray), start, end);
9045                });
9046
9047                function removeLeadingNewlines(comments: string[]) {
9048                    while (comments.length && (comments[0] === "\n" || comments[0] === "\r")) {
9049                        comments.shift();
9050                    }
9051                }
9052
9053                function removeTrailingWhitespace(comments: string[]) {
9054                    while (comments.length && comments[comments.length - 1].trim() === "") {
9055                        comments.pop();
9056                    }
9057                }
9058
9059                function isNextNonwhitespaceTokenEndOfFile(): boolean {
9060                    // We must use infinite lookahead, as there could be any number of newlines :(
9061                    while (true) {
9062                        nextTokenJSDoc();
9063                        if (token() === SyntaxKind.EndOfFileToken) {
9064                            return true;
9065                        }
9066                        if (!(token() === SyntaxKind.WhitespaceTrivia || token() === SyntaxKind.NewLineTrivia)) {
9067                            return false;
9068                        }
9069                    }
9070                }
9071
9072                function skipWhitespace(): void {
9073                    if (token() === SyntaxKind.WhitespaceTrivia || token() === SyntaxKind.NewLineTrivia) {
9074                        if (lookAhead(isNextNonwhitespaceTokenEndOfFile)) {
9075                            return; // Don't skip whitespace prior to EoF (or end of comment) - that shouldn't be included in any node's range
9076                        }
9077                    }
9078                    while (token() === SyntaxKind.WhitespaceTrivia || token() === SyntaxKind.NewLineTrivia) {
9079                        nextTokenJSDoc();
9080                    }
9081                }
9082
9083                function skipWhitespaceOrAsterisk(): string {
9084                    if (token() === SyntaxKind.WhitespaceTrivia || token() === SyntaxKind.NewLineTrivia) {
9085                        if (lookAhead(isNextNonwhitespaceTokenEndOfFile)) {
9086                            return ""; // Don't skip whitespace prior to EoF (or end of comment) - that shouldn't be included in any node's range
9087                        }
9088                    }
9089
9090                    let precedingLineBreak = scanner.hasPrecedingLineBreak();
9091                    let seenLineBreak = false;
9092                    let indentText = "";
9093                    while ((precedingLineBreak && token() === SyntaxKind.AsteriskToken) || token() === SyntaxKind.WhitespaceTrivia || token() === SyntaxKind.NewLineTrivia) {
9094                        indentText += scanner.getTokenText();
9095                        if (token() === SyntaxKind.NewLineTrivia) {
9096                            precedingLineBreak = true;
9097                            seenLineBreak = true;
9098                            indentText = "";
9099                        }
9100                        else if (token() === SyntaxKind.AsteriskToken) {
9101                            precedingLineBreak = false;
9102                        }
9103                        nextTokenJSDoc();
9104                    }
9105                    return seenLineBreak ? indentText : "";
9106                }
9107
9108                function parseTag(margin: number) {
9109                    Debug.assert(token() === SyntaxKind.AtToken);
9110                    const start = scanner.getTokenPos();
9111                    nextTokenJSDoc();
9112
9113                    const tagName = parseJSDocIdentifierName(/*message*/ undefined);
9114                    const indentText = skipWhitespaceOrAsterisk();
9115
9116                    let tag: JSDocTag | undefined;
9117                    switch (tagName.escapedText) {
9118                        case "author":
9119                            tag = parseAuthorTag(start, tagName, margin, indentText);
9120                            break;
9121                        case "implements":
9122                            tag = parseImplementsTag(start, tagName, margin, indentText);
9123                            break;
9124                        case "augments":
9125                        case "extends":
9126                            tag = parseAugmentsTag(start, tagName, margin, indentText);
9127                            break;
9128                        case "class":
9129                        case "constructor":
9130                            tag = parseSimpleTag(start, factory.createJSDocClassTag, tagName, margin, indentText);
9131                            break;
9132                        case "public":
9133                            tag = parseSimpleTag(start, factory.createJSDocPublicTag, tagName, margin, indentText);
9134                            break;
9135                        case "private":
9136                            tag = parseSimpleTag(start, factory.createJSDocPrivateTag, tagName, margin, indentText);
9137                            break;
9138                        case "protected":
9139                            tag = parseSimpleTag(start, factory.createJSDocProtectedTag, tagName, margin, indentText);
9140                            break;
9141                        case "readonly":
9142                            tag = parseSimpleTag(start, factory.createJSDocReadonlyTag, tagName, margin, indentText);
9143                            break;
9144                        case "override":
9145                            tag = parseSimpleTag(start, factory.createJSDocOverrideTag, tagName, margin, indentText);
9146                            break;
9147                        case "deprecated":
9148                            hasDeprecatedTag = true;
9149                            tag = parseSimpleTag(start, factory.createJSDocDeprecatedTag, tagName, margin, indentText);
9150                            break;
9151                        case "this":
9152                            tag = parseThisTag(start, tagName, margin, indentText);
9153                            break;
9154                        case "enum":
9155                            tag = parseEnumTag(start, tagName, margin, indentText);
9156                            break;
9157                        case "arg":
9158                        case "argument":
9159                        case "param":
9160                            return parseParameterOrPropertyTag(start, tagName, PropertyLikeParse.Parameter, margin);
9161                        case "return":
9162                        case "returns":
9163                            tag = parseReturnTag(start, tagName, margin, indentText);
9164                            break;
9165                        case "template":
9166                            tag = parseTemplateTag(start, tagName, margin, indentText);
9167                            break;
9168                        case "type":
9169                            tag = parseTypeTag(start, tagName, margin, indentText);
9170                            break;
9171                        case "typedef":
9172                            tag = parseTypedefTag(start, tagName, margin, indentText);
9173                            break;
9174                        case "callback":
9175                            tag = parseCallbackTag(start, tagName, margin, indentText);
9176                            break;
9177                        case "see":
9178                            tag = parseSeeTag(start, tagName, margin, indentText);
9179                            break;
9180                        default:
9181                            tag = parseUnknownTag(start, tagName, margin, indentText);
9182                            break;
9183                    }
9184                    return tag;
9185                }
9186
9187                function parseTrailingTagComments(pos: number, end: number, margin: number, indentText: string) {
9188                    // some tags, like typedef and callback, have already parsed their comments earlier
9189                    if (!indentText) {
9190                        margin += end - pos;
9191                    }
9192                    return parseTagComments(margin, indentText.slice(margin));
9193                }
9194
9195                function parseTagComments(indent: number, initialMargin?: string): string | NodeArray<JSDocComment> | undefined {
9196                    const commentsPos = getNodePos();
9197                    let comments: string[] = [];
9198                    const parts: JSDocComment[] = [];
9199                    let linkEnd;
9200                    let state = JSDocState.BeginningOfLine;
9201                    let previousWhitespace = true;
9202                    let margin: number | undefined;
9203                    function pushComment(text: string) {
9204                        if (!margin) {
9205                            margin = indent;
9206                        }
9207                        comments.push(text);
9208                        indent += text.length;
9209                    }
9210                    if (initialMargin !== undefined) {
9211                        // jump straight to saving comments if there is some initial indentation
9212                        if (initialMargin !== "") {
9213                            pushComment(initialMargin);
9214                        }
9215                        state = JSDocState.SawAsterisk;
9216                    }
9217                    let tok = token() as JSDocSyntaxKind;
9218                    loop: while (true) {
9219                        switch (tok) {
9220                            case SyntaxKind.NewLineTrivia:
9221                                state = JSDocState.BeginningOfLine;
9222                                // don't use pushComment here because we want to keep the margin unchanged
9223                                comments.push(scanner.getTokenText());
9224                                indent = 0;
9225                                break;
9226                            case SyntaxKind.AtToken:
9227                                if (state === JSDocState.SavingBackticks
9228                                    || state === JSDocState.SavingComments && (!previousWhitespace || lookAhead(isNextJSDocTokenWhitespace))) {
9229                                    // @ doesn't start a new tag inside ``, and inside a comment, only after whitespace or not before whitespace
9230                                    comments.push(scanner.getTokenText());
9231                                    break;
9232                                }
9233                                scanner.setTextPos(scanner.getTextPos() - 1);
9234                                // falls through
9235                            case SyntaxKind.EndOfFileToken:
9236                                // Done
9237                                break loop;
9238                            case SyntaxKind.WhitespaceTrivia:
9239                                if (state === JSDocState.SavingComments || state === JSDocState.SavingBackticks) {
9240                                    pushComment(scanner.getTokenText());
9241                                }
9242                                else {
9243                                    const whitespace = scanner.getTokenText();
9244                                    // if the whitespace crosses the margin, take only the whitespace that passes the margin
9245                                    if (margin !== undefined && indent + whitespace.length > margin) {
9246                                        comments.push(whitespace.slice(margin - indent));
9247                                    }
9248                                    indent += whitespace.length;
9249                                }
9250                                break;
9251                            case SyntaxKind.OpenBraceToken:
9252                                state = JSDocState.SavingComments;
9253                                const commentEnd = scanner.getStartPos();
9254                                const linkStart = scanner.getTextPos() - 1;
9255                                const link = parseJSDocLink(linkStart);
9256                                if (link) {
9257                                    parts.push(finishNode(factory.createJSDocText(comments.join("")), linkEnd ?? commentsPos, commentEnd));
9258                                    parts.push(link);
9259                                    comments = [];
9260                                    linkEnd = scanner.getTextPos();
9261                                }
9262                                else {
9263                                    pushComment(scanner.getTokenText());
9264                                }
9265                                break;
9266                            case SyntaxKind.BacktickToken:
9267                                if (state === JSDocState.SavingBackticks) {
9268                                    state = JSDocState.SavingComments;
9269                                }
9270                                else {
9271                                    state = JSDocState.SavingBackticks;
9272                                }
9273                                pushComment(scanner.getTokenText());
9274                                break;
9275                            case SyntaxKind.AsteriskToken:
9276                                if (state === JSDocState.BeginningOfLine) {
9277                                    // leading asterisks start recording on the *next* (non-whitespace) token
9278                                    state = JSDocState.SawAsterisk;
9279                                    indent += 1;
9280                                    break;
9281                                }
9282                                // record the * as a comment
9283                                // falls through
9284                            default:
9285                                if (state !== JSDocState.SavingBackticks) {
9286                                    state = JSDocState.SavingComments; // leading identifiers start recording as well
9287                                }
9288                                pushComment(scanner.getTokenText());
9289                                break;
9290                        }
9291                        previousWhitespace = token() === SyntaxKind.WhitespaceTrivia;
9292                        tok = nextTokenJSDoc();
9293                    }
9294
9295                    removeLeadingNewlines(comments);
9296                    removeTrailingWhitespace(comments);
9297                    if (parts.length) {
9298                        if (comments.length) {
9299                            parts.push(finishNode(factory.createJSDocText(comments.join("")), linkEnd ?? commentsPos));
9300                        }
9301                        return createNodeArray(parts, commentsPos, scanner.getTextPos());
9302                    }
9303                    else if (comments.length) {
9304                        return comments.join("");
9305                    }
9306                }
9307
9308                function isNextJSDocTokenWhitespace() {
9309                    const next = nextTokenJSDoc();
9310                    return next === SyntaxKind.WhitespaceTrivia || next === SyntaxKind.NewLineTrivia;
9311                }
9312
9313                function parseJSDocLink(start: number) {
9314                    const linkType = tryParse(parseJSDocLinkPrefix);
9315                    if (!linkType) {
9316                        return undefined;
9317                    }
9318                    nextTokenJSDoc(); // start at token after link, then skip any whitespace
9319                    skipWhitespace();
9320                    // parseEntityName logs an error for non-identifier, so create a MissingNode ourselves to avoid the error
9321                    const p2 = getNodePos();
9322                    let name: EntityName | JSDocMemberName | undefined = tokenIsIdentifierOrKeyword(token())
9323                        ? parseEntityName(/*allowReservedWords*/ true)
9324                        : undefined;
9325                    if (name) {
9326                        while (token() === SyntaxKind.PrivateIdentifier) {
9327                            reScanHashToken(); // rescan #id as # id
9328                            nextTokenJSDoc(); // then skip the #
9329                            name = finishNode(factory.createJSDocMemberName(name, parseIdentifier()), p2);
9330                        }
9331                    }
9332                    const text = [];
9333                    while (token() !== SyntaxKind.CloseBraceToken && token() !== SyntaxKind.NewLineTrivia && token() !== SyntaxKind.EndOfFileToken) {
9334                        text.push(scanner.getTokenText());
9335                        nextTokenJSDoc();
9336                    }
9337                    const create = linkType === "link" ? factory.createJSDocLink
9338                        : linkType === "linkcode" ? factory.createJSDocLinkCode
9339                        : factory.createJSDocLinkPlain;
9340                    return finishNode(create(name, text.join("")), start, scanner.getTextPos());
9341                }
9342
9343                function parseJSDocLinkPrefix() {
9344                    skipWhitespaceOrAsterisk();
9345                    if (token() === SyntaxKind.OpenBraceToken
9346                        && nextTokenJSDoc() === SyntaxKind.AtToken
9347                        && tokenIsIdentifierOrKeyword(nextTokenJSDoc())) {
9348                        const kind = scanner.getTokenValue();
9349                        if (isJSDocLinkTag(kind)) return kind;
9350                    }
9351                }
9352
9353                function isJSDocLinkTag(kind: string) {
9354                    return kind === "link" || kind === "linkcode" || kind === "linkplain";
9355                }
9356
9357                function parseUnknownTag(start: number, tagName: Identifier, indent: number, indentText: string) {
9358                    return finishNode(factory.createJSDocUnknownTag(tagName, parseTrailingTagComments(start, getNodePos(), indent, indentText)), start);
9359                }
9360
9361                function addTag(tag: JSDocTag | undefined): void {
9362                    if (!tag) {
9363                        return;
9364                    }
9365                    if (!tags) {
9366                        tags = [tag];
9367                        tagsPos = tag.pos;
9368                    }
9369                    else {
9370                        tags.push(tag);
9371                    }
9372                    tagsEnd = tag.end;
9373                }
9374
9375                function tryParseTypeExpression(): JSDocTypeExpression | undefined {
9376                    skipWhitespaceOrAsterisk();
9377                    return token() === SyntaxKind.OpenBraceToken ? parseJSDocTypeExpression() : undefined;
9378                }
9379
9380                function parseBracketNameInPropertyAndParamTag(): { name: EntityName, isBracketed: boolean } {
9381                    // Looking for something like '[foo]', 'foo', '[foo.bar]' or 'foo.bar'
9382                    const isBracketed = parseOptionalJsdoc(SyntaxKind.OpenBracketToken);
9383                    if (isBracketed) {
9384                        skipWhitespace();
9385                    }
9386                    // a markdown-quoted name: `arg` is not legal jsdoc, but occurs in the wild
9387                    const isBackquoted = parseOptionalJsdoc(SyntaxKind.BacktickToken);
9388                    const name = parseJSDocEntityName();
9389                    if (isBackquoted) {
9390                        parseExpectedTokenJSDoc(SyntaxKind.BacktickToken);
9391                    }
9392                    if (isBracketed) {
9393                        skipWhitespace();
9394                        // May have an optional default, e.g. '[foo = 42]'
9395                        if (parseOptionalToken(SyntaxKind.EqualsToken)) {
9396                            parseExpression();
9397                        }
9398
9399                        parseExpected(SyntaxKind.CloseBracketToken);
9400                    }
9401
9402                    return { name, isBracketed };
9403                }
9404
9405                function isObjectOrObjectArrayTypeReference(node: TypeNode): boolean {
9406                    switch (node.kind) {
9407                        case SyntaxKind.ObjectKeyword:
9408                            return true;
9409                        case SyntaxKind.ArrayType:
9410                            return isObjectOrObjectArrayTypeReference((node as ArrayTypeNode).elementType);
9411                        default:
9412                            return isTypeReferenceNode(node) && ts.isIdentifier(node.typeName) && node.typeName.escapedText === "Object" && !node.typeArguments;
9413                    }
9414                }
9415
9416                function parseParameterOrPropertyTag(start: number, tagName: Identifier, target: PropertyLikeParse, indent: number): JSDocParameterTag | JSDocPropertyTag {
9417                    let typeExpression = tryParseTypeExpression();
9418                    let isNameFirst = !typeExpression;
9419                    skipWhitespaceOrAsterisk();
9420
9421                    const { name, isBracketed } = parseBracketNameInPropertyAndParamTag();
9422                    const indentText = skipWhitespaceOrAsterisk();
9423
9424                    if (isNameFirst && !lookAhead(parseJSDocLinkPrefix)) {
9425                        typeExpression = tryParseTypeExpression();
9426                    }
9427
9428                    const comment = parseTrailingTagComments(start, getNodePos(), indent, indentText);
9429
9430                    const nestedTypeLiteral = target !== PropertyLikeParse.CallbackParameter && parseNestedTypeLiteral(typeExpression, name, target, indent);
9431                    if (nestedTypeLiteral) {
9432                        typeExpression = nestedTypeLiteral;
9433                        isNameFirst = true;
9434                    }
9435                    const result = target === PropertyLikeParse.Property
9436                        ? factory.createJSDocPropertyTag(tagName, name, isBracketed, typeExpression, isNameFirst, comment)
9437                        : factory.createJSDocParameterTag(tagName, name, isBracketed, typeExpression, isNameFirst, comment);
9438                    return finishNode(result, start);
9439                }
9440
9441                function parseNestedTypeLiteral(typeExpression: JSDocTypeExpression | undefined, name: EntityName, target: PropertyLikeParse, indent: number) {
9442                    if (typeExpression && isObjectOrObjectArrayTypeReference(typeExpression.type)) {
9443                        const pos = getNodePos();
9444                        let child: JSDocPropertyLikeTag | JSDocTypeTag | false;
9445                        let children: JSDocPropertyLikeTag[] | undefined;
9446                        while (child = tryParse(() => parseChildParameterOrPropertyTag(target, indent, name))) {
9447                            if (child.kind === SyntaxKind.JSDocParameterTag || child.kind === SyntaxKind.JSDocPropertyTag) {
9448                                children = append(children, child);
9449                            }
9450                        }
9451                        if (children) {
9452                            const literal = finishNode(factory.createJSDocTypeLiteral(children, typeExpression.type.kind === SyntaxKind.ArrayType), pos);
9453                            return finishNode(factory.createJSDocTypeExpression(literal), pos);
9454                        }
9455                    }
9456                }
9457
9458                function parseReturnTag(start: number, tagName: Identifier, indent: number, indentText: string): JSDocReturnTag {
9459                    if (some(tags, isJSDocReturnTag)) {
9460                        parseErrorAt(tagName.pos, scanner.getTokenPos(), Diagnostics._0_tag_already_specified, tagName.escapedText);
9461                    }
9462
9463                    const typeExpression = tryParseTypeExpression();
9464                    return finishNode(factory.createJSDocReturnTag(tagName, typeExpression, parseTrailingTagComments(start, getNodePos(), indent, indentText)), start);
9465                }
9466
9467                function parseTypeTag(start: number, tagName: Identifier, indent?: number, indentText?: string): JSDocTypeTag {
9468                    if (some(tags, isJSDocTypeTag)) {
9469                        parseErrorAt(tagName.pos, scanner.getTokenPos(), Diagnostics._0_tag_already_specified, tagName.escapedText);
9470                    }
9471
9472                    const typeExpression = parseJSDocTypeExpression(/*mayOmitBraces*/ true);
9473                    const comments = indent !== undefined && indentText !== undefined ? parseTrailingTagComments(start, getNodePos(), indent, indentText) : undefined;
9474                    return finishNode(factory.createJSDocTypeTag(tagName, typeExpression, comments), start);
9475                }
9476
9477                function parseSeeTag(start: number, tagName: Identifier, indent?: number, indentText?: string): JSDocSeeTag {
9478                    const isMarkdownOrJSDocLink = token() === SyntaxKind.OpenBracketToken
9479                        || lookAhead(() => nextTokenJSDoc() === SyntaxKind.AtToken && tokenIsIdentifierOrKeyword(nextTokenJSDoc()) && isJSDocLinkTag(scanner.getTokenValue()));
9480                    const nameExpression = isMarkdownOrJSDocLink ? undefined : parseJSDocNameReference();
9481                    const comments = indent !== undefined && indentText !== undefined ? parseTrailingTagComments(start, getNodePos(), indent, indentText) : undefined;
9482                    return finishNode(factory.createJSDocSeeTag(tagName, nameExpression, comments), start);
9483                }
9484
9485                function parseAuthorTag(start: number, tagName: Identifier, indent: number, indentText: string): JSDocAuthorTag {
9486                    const commentStart = getNodePos();
9487                    const textOnly = parseAuthorNameAndEmail();
9488                    let commentEnd = scanner.getStartPos();
9489                    const comments = parseTrailingTagComments(start, commentEnd, indent, indentText);
9490                    if (!comments) {
9491                        commentEnd = scanner.getStartPos();
9492                    }
9493                    const allParts = typeof comments !== "string"
9494                        ? createNodeArray(concatenate([finishNode(textOnly, commentStart, commentEnd)], comments) as JSDocComment[], commentStart) // cast away readonly
9495                        : textOnly.text + comments;
9496                    return finishNode(factory.createJSDocAuthorTag(tagName, allParts), start);
9497                }
9498
9499                function parseAuthorNameAndEmail(): JSDocText {
9500                    const comments: string[] = [];
9501                    let inEmail = false;
9502                    let token = scanner.getToken();
9503                    while (token !== SyntaxKind.EndOfFileToken && token !== SyntaxKind.NewLineTrivia) {
9504                        if (token === SyntaxKind.LessThanToken) {
9505                            inEmail = true;
9506                        }
9507                        else if (token === SyntaxKind.AtToken && !inEmail) {
9508                            break;
9509                        }
9510                        else if (token === SyntaxKind.GreaterThanToken && inEmail) {
9511                            comments.push(scanner.getTokenText());
9512                            scanner.setTextPos(scanner.getTokenPos() + 1);
9513                            break;
9514                        }
9515                        comments.push(scanner.getTokenText());
9516                        token = nextTokenJSDoc();
9517                    }
9518
9519                    return factory.createJSDocText(comments.join(""));
9520                }
9521
9522                function parseImplementsTag(start: number, tagName: Identifier, margin: number, indentText: string): JSDocImplementsTag {
9523                    const className = parseExpressionWithTypeArgumentsForAugments();
9524                    return finishNode(factory.createJSDocImplementsTag(tagName, className, parseTrailingTagComments(start, getNodePos(), margin, indentText)), start);
9525                }
9526
9527                function parseAugmentsTag(start: number, tagName: Identifier, margin: number, indentText: string): JSDocAugmentsTag {
9528                    const className = parseExpressionWithTypeArgumentsForAugments();
9529                    return finishNode(factory.createJSDocAugmentsTag(tagName, className, parseTrailingTagComments(start, getNodePos(), margin, indentText)), start);
9530                }
9531
9532                function parseExpressionWithTypeArgumentsForAugments(): ExpressionWithTypeArguments & { expression: Identifier | PropertyAccessEntityNameExpression } {
9533                    const usedBrace = parseOptional(SyntaxKind.OpenBraceToken);
9534                    const pos = getNodePos();
9535                    const expression = parsePropertyAccessEntityNameExpression();
9536                    const typeArguments = tryParseTypeArguments();
9537                    const node = factory.createExpressionWithTypeArguments(expression, typeArguments) as ExpressionWithTypeArguments & { expression: Identifier | PropertyAccessEntityNameExpression };
9538                    const res = finishNode(node, pos);
9539                    if (usedBrace) {
9540                        parseExpected(SyntaxKind.CloseBraceToken);
9541                    }
9542                    return res;
9543                }
9544
9545                function parsePropertyAccessEntityNameExpression() {
9546                    const pos = getNodePos();
9547                    let node: Identifier | PropertyAccessEntityNameExpression = parseJSDocIdentifierName();
9548                    while (parseOptional(SyntaxKind.DotToken)) {
9549                        const name = parseJSDocIdentifierName();
9550                        node = finishNode(factory.createPropertyAccessExpression(node, name), pos) as PropertyAccessEntityNameExpression;
9551                    }
9552                    return node;
9553                }
9554
9555                function parseSimpleTag(start: number, createTag: (tagName: Identifier | undefined, comment?: string | NodeArray<JSDocComment>) => JSDocTag, tagName: Identifier, margin: number, indentText: string): JSDocTag {
9556                    return finishNode(createTag(tagName, parseTrailingTagComments(start, getNodePos(), margin, indentText)), start);
9557                }
9558
9559                function parseThisTag(start: number, tagName: Identifier, margin: number, indentText: string): JSDocThisTag {
9560                    const typeExpression = parseJSDocTypeExpression(/*mayOmitBraces*/ true);
9561                    skipWhitespace();
9562                    return finishNode(factory.createJSDocThisTag(tagName, typeExpression, parseTrailingTagComments(start, getNodePos(), margin, indentText)), start);
9563                }
9564
9565                function parseEnumTag(start: number, tagName: Identifier, margin: number, indentText: string): JSDocEnumTag {
9566                    const typeExpression = parseJSDocTypeExpression(/*mayOmitBraces*/ true);
9567                    skipWhitespace();
9568                    return finishNode(factory.createJSDocEnumTag(tagName, typeExpression, parseTrailingTagComments(start, getNodePos(), margin, indentText)), start);
9569                }
9570
9571                function parseTypedefTag(start: number, tagName: Identifier, indent: number, indentText: string): JSDocTypedefTag {
9572                    let typeExpression: JSDocTypeExpression | JSDocTypeLiteral | undefined = tryParseTypeExpression();
9573                    skipWhitespaceOrAsterisk();
9574
9575                    const fullName = parseJSDocTypeNameWithNamespace();
9576                    skipWhitespace();
9577                    let comment = parseTagComments(indent);
9578
9579                    let end: number | undefined;
9580                    if (!typeExpression || isObjectOrObjectArrayTypeReference(typeExpression.type)) {
9581                        let child: JSDocTypeTag | JSDocPropertyTag | false;
9582                        let childTypeTag: JSDocTypeTag | undefined;
9583                        let jsDocPropertyTags: JSDocPropertyTag[] | undefined;
9584                        let hasChildren = false;
9585                        while (child = tryParse(() => parseChildPropertyTag(indent))) {
9586                            hasChildren = true;
9587                            if (child.kind === SyntaxKind.JSDocTypeTag) {
9588                                if (childTypeTag) {
9589                                    const lastError = parseErrorAtCurrentToken(Diagnostics.A_JSDoc_typedef_comment_may_not_contain_multiple_type_tags);
9590                                    if (lastError) {
9591                                        addRelatedInfo(lastError, createDetachedDiagnostic(fileName, 0, 0, Diagnostics.The_tag_was_first_specified_here));
9592                                    }
9593                                    break;
9594                                }
9595                                else {
9596                                    childTypeTag = child;
9597                                }
9598                            }
9599                            else {
9600                                jsDocPropertyTags = append(jsDocPropertyTags, child);
9601                            }
9602                        }
9603                        if (hasChildren) {
9604                            const isArrayType = typeExpression && typeExpression.type.kind === SyntaxKind.ArrayType;
9605                            const jsdocTypeLiteral = factory.createJSDocTypeLiteral(jsDocPropertyTags, isArrayType);
9606                            typeExpression = childTypeTag && childTypeTag.typeExpression && !isObjectOrObjectArrayTypeReference(childTypeTag.typeExpression.type) ?
9607                                childTypeTag.typeExpression :
9608                                finishNode(jsdocTypeLiteral, start);
9609                            end = typeExpression.end;
9610                        }
9611                    }
9612
9613                    // Only include the characters between the name end and the next token if a comment was actually parsed out - otherwise it's just whitespace
9614                    end = end || comment !== undefined ?
9615                        getNodePos() :
9616                        (fullName ?? typeExpression ?? tagName).end;
9617
9618                    if (!comment) {
9619                        comment = parseTrailingTagComments(start, end, indent, indentText);
9620                    }
9621
9622                    const typedefTag = factory.createJSDocTypedefTag(tagName, typeExpression, fullName, comment);
9623                    return finishNode(typedefTag, start, end);
9624                }
9625
9626                function parseJSDocTypeNameWithNamespace(nested?: boolean) {
9627                    const pos = scanner.getTokenPos();
9628                    if (!tokenIsIdentifierOrKeyword(token())) {
9629                        return undefined;
9630                    }
9631                    const typeNameOrNamespaceName = parseJSDocIdentifierName();
9632                    if (parseOptional(SyntaxKind.DotToken)) {
9633                        const body = parseJSDocTypeNameWithNamespace(/*nested*/ true);
9634                        const jsDocNamespaceNode = factory.createModuleDeclaration(
9635                            /*modifiers*/ undefined,
9636                            typeNameOrNamespaceName,
9637                            body,
9638                            nested ? NodeFlags.NestedNamespace : undefined
9639                        ) as JSDocNamespaceDeclaration;
9640                        return finishNode(jsDocNamespaceNode, pos);
9641                    }
9642
9643                    if (nested) {
9644                        typeNameOrNamespaceName.isInJSDocNamespace = true;
9645                    }
9646                    return typeNameOrNamespaceName;
9647                }
9648
9649
9650                function parseCallbackTagParameters(indent: number) {
9651                    const pos = getNodePos();
9652                    let child: JSDocParameterTag | false;
9653                    let parameters;
9654                    while (child = tryParse(() => parseChildParameterOrPropertyTag(PropertyLikeParse.CallbackParameter, indent) as JSDocParameterTag)) {
9655                        parameters = append(parameters, child);
9656                    }
9657                    return createNodeArray(parameters || [], pos);
9658                }
9659
9660                function parseCallbackTag(start: number, tagName: Identifier, indent: number, indentText: string): JSDocCallbackTag {
9661                    const fullName = parseJSDocTypeNameWithNamespace();
9662                    skipWhitespace();
9663                    let comment = parseTagComments(indent);
9664                    const parameters = parseCallbackTagParameters(indent);
9665                    const returnTag = tryParse(() => {
9666                        if (parseOptionalJsdoc(SyntaxKind.AtToken)) {
9667                            const tag = parseTag(indent);
9668                            if (tag && tag.kind === SyntaxKind.JSDocReturnTag) {
9669                                return tag as JSDocReturnTag;
9670                            }
9671                        }
9672                    });
9673                    const typeExpression = finishNode(factory.createJSDocSignature(/*typeParameters*/ undefined, parameters, returnTag), start);
9674                    if (!comment) {
9675                        comment = parseTrailingTagComments(start, getNodePos(), indent, indentText);
9676                    }
9677                    const end = comment !== undefined ? getNodePos() : typeExpression.end;
9678                    return finishNode(factory.createJSDocCallbackTag(tagName, typeExpression, fullName, comment), start, end);
9679                }
9680
9681                function escapedTextsEqual(a: EntityName, b: EntityName): boolean {
9682                    while (!ts.isIdentifier(a) || !ts.isIdentifier(b)) {
9683                        if (!ts.isIdentifier(a) && !ts.isIdentifier(b) && a.right.escapedText === b.right.escapedText) {
9684                            a = a.left;
9685                            b = b.left;
9686                        }
9687                        else {
9688                            return false;
9689                        }
9690                    }
9691                    return a.escapedText === b.escapedText;
9692                }
9693
9694                function parseChildPropertyTag(indent: number) {
9695                    return parseChildParameterOrPropertyTag(PropertyLikeParse.Property, indent) as JSDocTypeTag | JSDocPropertyTag | false;
9696                }
9697
9698                function parseChildParameterOrPropertyTag(target: PropertyLikeParse, indent: number, name?: EntityName): JSDocTypeTag | JSDocPropertyTag | JSDocParameterTag | false {
9699                    let canParseTag = true;
9700                    let seenAsterisk = false;
9701                    while (true) {
9702                        switch (nextTokenJSDoc()) {
9703                            case SyntaxKind.AtToken:
9704                                if (canParseTag) {
9705                                    const child = tryParseChildTag(target, indent);
9706                                    if (child && (child.kind === SyntaxKind.JSDocParameterTag || child.kind === SyntaxKind.JSDocPropertyTag) &&
9707                                        target !== PropertyLikeParse.CallbackParameter &&
9708                                        name && (ts.isIdentifier(child.name) || !escapedTextsEqual(name, child.name.left))) {
9709                                        return false;
9710                                    }
9711                                    return child;
9712                                }
9713                                seenAsterisk = false;
9714                                break;
9715                            case SyntaxKind.NewLineTrivia:
9716                                canParseTag = true;
9717                                seenAsterisk = false;
9718                                break;
9719                            case SyntaxKind.AsteriskToken:
9720                                if (seenAsterisk) {
9721                                    canParseTag = false;
9722                                }
9723                                seenAsterisk = true;
9724                                break;
9725                            case SyntaxKind.Identifier:
9726                                canParseTag = false;
9727                                break;
9728                            case SyntaxKind.EndOfFileToken:
9729                                return false;
9730                        }
9731                    }
9732                }
9733
9734                function tryParseChildTag(target: PropertyLikeParse, indent: number): JSDocTypeTag | JSDocPropertyTag | JSDocParameterTag | false {
9735                    Debug.assert(token() === SyntaxKind.AtToken);
9736                    const start = scanner.getStartPos();
9737                    nextTokenJSDoc();
9738
9739                    const tagName = parseJSDocIdentifierName();
9740                    skipWhitespace();
9741                    let t: PropertyLikeParse;
9742                    switch (tagName.escapedText) {
9743                        case "type":
9744                            return target === PropertyLikeParse.Property && parseTypeTag(start, tagName);
9745                        case "prop":
9746                        case "property":
9747                            t = PropertyLikeParse.Property;
9748                            break;
9749                        case "arg":
9750                        case "argument":
9751                        case "param":
9752                            t = PropertyLikeParse.Parameter | PropertyLikeParse.CallbackParameter;
9753                            break;
9754                        default:
9755                            return false;
9756                    }
9757                    if (!(target & t)) {
9758                        return false;
9759                    }
9760                    return parseParameterOrPropertyTag(start, tagName, target, indent);
9761                }
9762
9763                function parseTemplateTagTypeParameter() {
9764                    const typeParameterPos = getNodePos();
9765                    const isBracketed = parseOptionalJsdoc(SyntaxKind.OpenBracketToken);
9766                    if (isBracketed) {
9767                        skipWhitespace();
9768                    }
9769                    const name = parseJSDocIdentifierName(Diagnostics.Unexpected_token_A_type_parameter_name_was_expected_without_curly_braces);
9770
9771                    let defaultType: TypeNode | undefined;
9772                    if (isBracketed) {
9773                        skipWhitespace();
9774                        parseExpected(SyntaxKind.EqualsToken);
9775                        defaultType = doInsideOfContext(NodeFlags.JSDoc, parseJSDocType);
9776                        parseExpected(SyntaxKind.CloseBracketToken);
9777                    }
9778
9779                    if (nodeIsMissing(name)) {
9780                        return undefined;
9781                    }
9782                    return finishNode(factory.createTypeParameterDeclaration(/*modifiers*/ undefined, name, /*constraint*/ undefined, defaultType), typeParameterPos);
9783                }
9784
9785                function parseTemplateTagTypeParameters() {
9786                    const pos = getNodePos();
9787                    const typeParameters = [];
9788                    do {
9789                        skipWhitespace();
9790                        const node = parseTemplateTagTypeParameter();
9791                        if (node !== undefined) {
9792                            typeParameters.push(node);
9793                        }
9794                        skipWhitespaceOrAsterisk();
9795                    } while (parseOptionalJsdoc(SyntaxKind.CommaToken));
9796                    return createNodeArray(typeParameters, pos);
9797                }
9798
9799                function parseTemplateTag(start: number, tagName: Identifier, indent: number, indentText: string): JSDocTemplateTag {
9800                    // The template tag looks like one of the following:
9801                    //   @template T,U,V
9802                    //   @template {Constraint} T
9803                    //
9804                    // According to the [closure docs](https://github.com/google/closure-compiler/wiki/Generic-Types#multiple-bounded-template-types):
9805                    //   > Multiple bounded generics cannot be declared on the same line. For the sake of clarity, if multiple templates share the same
9806                    //   > type bound they must be declared on separate lines.
9807                    //
9808                    // TODO: Determine whether we should enforce this in the checker.
9809                    // TODO: Consider moving the `constraint` to the first type parameter as we could then remove `getEffectiveConstraintOfTypeParameter`.
9810                    // TODO: Consider only parsing a single type parameter if there is a constraint.
9811                    const constraint = token() === SyntaxKind.OpenBraceToken ? parseJSDocTypeExpression() : undefined;
9812                    const typeParameters = parseTemplateTagTypeParameters();
9813                    return finishNode(factory.createJSDocTemplateTag(tagName, constraint, typeParameters, parseTrailingTagComments(start, getNodePos(), indent, indentText)), start);
9814                }
9815
9816                function parseOptionalJsdoc(t: JSDocSyntaxKind): boolean {
9817                    if (token() === t) {
9818                        nextTokenJSDoc();
9819                        return true;
9820                    }
9821                    return false;
9822                }
9823
9824                function parseJSDocEntityName(): EntityName {
9825                    let entity: EntityName = parseJSDocIdentifierName();
9826                    if (parseOptional(SyntaxKind.OpenBracketToken)) {
9827                        parseExpected(SyntaxKind.CloseBracketToken);
9828                        // Note that y[] is accepted as an entity name, but the postfix brackets are not saved for checking.
9829                        // Technically usejsdoc.org requires them for specifying a property of a type equivalent to Array<{ x: ...}>
9830                        // but it's not worth it to enforce that restriction.
9831                    }
9832                    while (parseOptional(SyntaxKind.DotToken)) {
9833                        const name = parseJSDocIdentifierName();
9834                        if (parseOptional(SyntaxKind.OpenBracketToken)) {
9835                            parseExpected(SyntaxKind.CloseBracketToken);
9836                        }
9837                        entity = createQualifiedName(entity, name);
9838                    }
9839                    return entity;
9840                }
9841
9842                function parseJSDocIdentifierName(message?: DiagnosticMessage): Identifier {
9843                    if (!tokenIsIdentifierOrKeyword(token())) {
9844                        return createMissingNode<Identifier>(SyntaxKind.Identifier, /*reportAtCurrentPosition*/ !message, message || Diagnostics.Identifier_expected);
9845                    }
9846
9847                    identifierCount++;
9848                    const pos = scanner.getTokenPos();
9849                    const end = scanner.getTextPos();
9850                    const originalKeywordKind = token();
9851                    const text = internIdentifier(scanner.getTokenValue());
9852                    const result = finishNode(factory.createIdentifier(text, /*typeArguments*/ undefined, originalKeywordKind), pos, end);
9853                    nextTokenJSDoc();
9854                    return result;
9855                }
9856            }
9857        }
9858    }
9859
9860    namespace IncrementalParser {
9861        export function updateSourceFile(sourceFile: SourceFile, newText: string, textChangeRange: TextChangeRange, aggressiveChecks: boolean): SourceFile {
9862            aggressiveChecks = aggressiveChecks || Debug.shouldAssert(AssertionLevel.Aggressive);
9863
9864            checkChangeRange(sourceFile, newText, textChangeRange, aggressiveChecks);
9865            if (textChangeRangeIsUnchanged(textChangeRange)) {
9866                // if the text didn't change, then we can just return our current source file as-is.
9867                return sourceFile;
9868            }
9869
9870            if (sourceFile.statements.length === 0) {
9871                // If we don't have any statements in the current source file, then there's no real
9872                // way to incrementally parse.  So just do a full parse instead.
9873                return Parser.parseSourceFile(sourceFile.fileName, newText, sourceFile.languageVersion, /*syntaxCursor*/ undefined, /*setParentNodes*/ true, sourceFile.scriptKind, sourceFile.setExternalModuleIndicator);
9874            }
9875
9876            // Make sure we're not trying to incrementally update a source file more than once.  Once
9877            // we do an update the original source file is considered unusable from that point onwards.
9878            //
9879            // This is because we do incremental parsing in-place.  i.e. we take nodes from the old
9880            // tree and give them new positions and parents.  From that point on, trusting the old
9881            // tree at all is not possible as far too much of it may violate invariants.
9882            const incrementalSourceFile = sourceFile as Node as IncrementalNode;
9883            Debug.assert(!incrementalSourceFile.hasBeenIncrementallyParsed);
9884            incrementalSourceFile.hasBeenIncrementallyParsed = true;
9885            Parser.fixupParentReferences(incrementalSourceFile);
9886            const oldText = sourceFile.text;
9887            const syntaxCursor = createSyntaxCursor(sourceFile);
9888
9889            // Make the actual change larger so that we know to reparse anything whose lookahead
9890            // might have intersected the change.
9891            const changeRange = extendToAffectedRange(sourceFile, textChangeRange);
9892            checkChangeRange(sourceFile, newText, changeRange, aggressiveChecks);
9893
9894            // Ensure that extending the affected range only moved the start of the change range
9895            // earlier in the file.
9896            Debug.assert(changeRange.span.start <= textChangeRange.span.start);
9897            Debug.assert(textSpanEnd(changeRange.span) === textSpanEnd(textChangeRange.span));
9898            Debug.assert(textSpanEnd(textChangeRangeNewSpan(changeRange)) === textSpanEnd(textChangeRangeNewSpan(textChangeRange)));
9899
9900            // The is the amount the nodes after the edit range need to be adjusted.  It can be
9901            // positive (if the edit added characters), negative (if the edit deleted characters)
9902            // or zero (if this was a pure overwrite with nothing added/removed).
9903            const delta = textChangeRangeNewSpan(changeRange).length - changeRange.span.length;
9904
9905            // If we added or removed characters during the edit, then we need to go and adjust all
9906            // the nodes after the edit.  Those nodes may move forward (if we inserted chars) or they
9907            // may move backward (if we deleted chars).
9908            //
9909            // Doing this helps us out in two ways.  First, it means that any nodes/tokens we want
9910            // to reuse are already at the appropriate position in the new text.  That way when we
9911            // reuse them, we don't have to figure out if they need to be adjusted.  Second, it makes
9912            // it very easy to determine if we can reuse a node.  If the node's position is at where
9913            // we are in the text, then we can reuse it.  Otherwise we can't.  If the node's position
9914            // is ahead of us, then we'll need to rescan tokens.  If the node's position is behind
9915            // us, then we'll need to skip it or crumble it as appropriate
9916            //
9917            // We will also adjust the positions of nodes that intersect the change range as well.
9918            // By doing this, we ensure that all the positions in the old tree are consistent, not
9919            // just the positions of nodes entirely before/after the change range.  By being
9920            // consistent, we can then easily map from positions to nodes in the old tree easily.
9921            //
9922            // Also, mark any syntax elements that intersect the changed span.  We know, up front,
9923            // that we cannot reuse these elements.
9924            updateTokenPositionsAndMarkElements(incrementalSourceFile,
9925                changeRange.span.start, textSpanEnd(changeRange.span), textSpanEnd(textChangeRangeNewSpan(changeRange)), delta, oldText, newText, aggressiveChecks);
9926
9927            // Now that we've set up our internal incremental state just proceed and parse the
9928            // source file in the normal fashion.  When possible the parser will retrieve and
9929            // reuse nodes from the old tree.
9930            //
9931            // Note: passing in 'true' for setNodeParents is very important.  When incrementally
9932            // parsing, we will be reusing nodes from the old tree, and placing it into new
9933            // parents.  If we don't set the parents now, we'll end up with an observably
9934            // inconsistent tree.  Setting the parents on the new tree should be very fast.  We
9935            // will immediately bail out of walking any subtrees when we can see that their parents
9936            // are already correct.
9937            const result = Parser.parseSourceFile(sourceFile.fileName, newText, sourceFile.languageVersion, syntaxCursor, /*setParentNodes*/ true, sourceFile.scriptKind, sourceFile.setExternalModuleIndicator);
9938            result.commentDirectives = getNewCommentDirectives(
9939                sourceFile.commentDirectives,
9940                result.commentDirectives,
9941                changeRange.span.start,
9942                textSpanEnd(changeRange.span),
9943                delta,
9944                oldText,
9945                newText,
9946                aggressiveChecks
9947            );
9948            result.impliedNodeFormat = sourceFile.impliedNodeFormat;
9949            return result;
9950        }
9951
9952        function getNewCommentDirectives(
9953            oldDirectives: CommentDirective[] | undefined,
9954            newDirectives: CommentDirective[] | undefined,
9955            changeStart: number,
9956            changeRangeOldEnd: number,
9957            delta: number,
9958            oldText: string,
9959            newText: string,
9960            aggressiveChecks: boolean
9961        ): CommentDirective[] | undefined {
9962            if (!oldDirectives) return newDirectives;
9963            let commentDirectives: CommentDirective[] | undefined;
9964            let addedNewlyScannedDirectives = false;
9965            for (const directive of oldDirectives) {
9966                const { range, type } = directive;
9967                // Range before the change
9968                if (range.end < changeStart) {
9969                    commentDirectives = append(commentDirectives, directive);
9970                }
9971                else if (range.pos > changeRangeOldEnd) {
9972                    addNewlyScannedDirectives();
9973                    // Node is entirely past the change range.  We need to move both its pos and
9974                    // end, forward or backward appropriately.
9975                    const updatedDirective: CommentDirective = {
9976                        range: { pos: range.pos + delta, end: range.end + delta },
9977                        type
9978                    };
9979                    commentDirectives = append(commentDirectives, updatedDirective);
9980                    if (aggressiveChecks) {
9981                        Debug.assert(oldText.substring(range.pos, range.end) === newText.substring(updatedDirective.range.pos, updatedDirective.range.end));
9982                    }
9983                }
9984                // Ignore ranges that fall in change range
9985            }
9986            addNewlyScannedDirectives();
9987            return commentDirectives;
9988
9989            function addNewlyScannedDirectives() {
9990                if (addedNewlyScannedDirectives) return;
9991                addedNewlyScannedDirectives = true;
9992                if (!commentDirectives) {
9993                    commentDirectives = newDirectives;
9994                }
9995                else if (newDirectives) {
9996                    commentDirectives.push(...newDirectives);
9997                }
9998            }
9999        }
10000
10001        function moveElementEntirelyPastChangeRange(element: IncrementalElement, isArray: boolean, delta: number, oldText: string, newText: string, aggressiveChecks: boolean) {
10002            if (isArray) {
10003                visitArray(element as IncrementalNodeArray);
10004            }
10005            else {
10006                visitNode(element as IncrementalNode);
10007            }
10008            return;
10009
10010            function visitNode(node: IncrementalNode) {
10011                let text = "";
10012                if (aggressiveChecks && shouldCheckNode(node)) {
10013                    text = oldText.substring(node.pos, node.end);
10014                }
10015
10016                // Ditch any existing LS children we may have created.  This way we can avoid
10017                // moving them forward.
10018                if (node._children) {
10019                    node._children = undefined;
10020                }
10021
10022                setTextRangePosEnd(node, node.pos + delta, node.end + delta);
10023
10024                if (aggressiveChecks && shouldCheckNode(node)) {
10025                    Debug.assert(text === newText.substring(node.pos, node.end));
10026                }
10027
10028                forEachChild(node, visitNode, visitArray);
10029                if (hasJSDocNodes(node)) {
10030                    for (const jsDocComment of node.jsDoc!) {
10031                        visitNode(jsDocComment as Node as IncrementalNode);
10032                    }
10033                }
10034                checkNodePositions(node, aggressiveChecks);
10035            }
10036
10037            function visitArray(array: IncrementalNodeArray) {
10038                array._children = undefined;
10039                setTextRangePosEnd(array, array.pos + delta, array.end + delta);
10040
10041                for (const node of array) {
10042                    visitNode(node);
10043                }
10044            }
10045        }
10046
10047        function shouldCheckNode(node: Node) {
10048            switch (node.kind) {
10049                case SyntaxKind.StringLiteral:
10050                case SyntaxKind.NumericLiteral:
10051                case SyntaxKind.Identifier:
10052                    return true;
10053            }
10054
10055            return false;
10056        }
10057
10058        function adjustIntersectingElement(element: IncrementalElement, changeStart: number, changeRangeOldEnd: number, changeRangeNewEnd: number, delta: number) {
10059            Debug.assert(element.end >= changeStart, "Adjusting an element that was entirely before the change range");
10060            Debug.assert(element.pos <= changeRangeOldEnd, "Adjusting an element that was entirely after the change range");
10061            Debug.assert(element.pos <= element.end);
10062
10063            // We have an element that intersects the change range in some way.  It may have its
10064            // start, or its end (or both) in the changed range.  We want to adjust any part
10065            // that intersects such that the final tree is in a consistent state.  i.e. all
10066            // children have spans within the span of their parent, and all siblings are ordered
10067            // properly.
10068
10069            // We may need to update both the 'pos' and the 'end' of the element.
10070
10071            // If the 'pos' is before the start of the change, then we don't need to touch it.
10072            // If it isn't, then the 'pos' must be inside the change.  How we update it will
10073            // depend if delta is positive or negative. If delta is positive then we have
10074            // something like:
10075            //
10076            //  -------------------AAA-----------------
10077            //  -------------------BBBCCCCCCC-----------------
10078            //
10079            // In this case, we consider any node that started in the change range to still be
10080            // starting at the same position.
10081            //
10082            // however, if the delta is negative, then we instead have something like this:
10083            //
10084            //  -------------------XXXYYYYYYY-----------------
10085            //  -------------------ZZZ-----------------
10086            //
10087            // In this case, any element that started in the 'X' range will keep its position.
10088            // However any element that started after that will have their pos adjusted to be
10089            // at the end of the new range.  i.e. any node that started in the 'Y' range will
10090            // be adjusted to have their start at the end of the 'Z' range.
10091            //
10092            // The element will keep its position if possible.  Or Move backward to the new-end
10093            // if it's in the 'Y' range.
10094            const pos = Math.min(element.pos, changeRangeNewEnd);
10095
10096            // If the 'end' is after the change range, then we always adjust it by the delta
10097            // amount.  However, if the end is in the change range, then how we adjust it
10098            // will depend on if delta is positive or negative.  If delta is positive then we
10099            // have something like:
10100            //
10101            //  -------------------AAA-----------------
10102            //  -------------------BBBCCCCCCC-----------------
10103            //
10104            // In this case, we consider any node that ended inside the change range to keep its
10105            // end position.
10106            //
10107            // however, if the delta is negative, then we instead have something like this:
10108            //
10109            //  -------------------XXXYYYYYYY-----------------
10110            //  -------------------ZZZ-----------------
10111            //
10112            // In this case, any element that ended in the 'X' range will keep its position.
10113            // However any element that ended after that will have their pos adjusted to be
10114            // at the end of the new range.  i.e. any node that ended in the 'Y' range will
10115            // be adjusted to have their end at the end of the 'Z' range.
10116            const end = element.end >= changeRangeOldEnd ?
10117                // Element ends after the change range.  Always adjust the end pos.
10118                element.end + delta :
10119                // Element ends in the change range.  The element will keep its position if
10120                // possible. Or Move backward to the new-end if it's in the 'Y' range.
10121                Math.min(element.end, changeRangeNewEnd);
10122
10123            Debug.assert(pos <= end);
10124            if (element.parent) {
10125                Debug.assertGreaterThanOrEqual(pos, element.parent.pos);
10126                Debug.assertLessThanOrEqual(end, element.parent.end);
10127            }
10128
10129            setTextRangePosEnd(element, pos, end);
10130        }
10131
10132        function checkNodePositions(node: Node, aggressiveChecks: boolean) {
10133            if (aggressiveChecks) {
10134                let pos = node.pos;
10135                const visitNode = (child: Node) => {
10136                    Debug.assert(child.pos >= pos);
10137                    pos = child.end;
10138                };
10139                if (hasJSDocNodes(node)) {
10140                    for (const jsDocComment of node.jsDoc!) {
10141                        visitNode(jsDocComment);
10142                    }
10143                }
10144                forEachChild(node, visitNode);
10145                Debug.assert(pos <= node.end);
10146            }
10147        }
10148
10149        function updateTokenPositionsAndMarkElements(
10150            sourceFile: IncrementalNode,
10151            changeStart: number,
10152            changeRangeOldEnd: number,
10153            changeRangeNewEnd: number,
10154            delta: number,
10155            oldText: string,
10156            newText: string,
10157            aggressiveChecks: boolean): void {
10158
10159            visitNode(sourceFile);
10160            return;
10161
10162            function visitNode(child: IncrementalNode) {
10163                Debug.assert(child.pos <= child.end);
10164                if (child.pos > changeRangeOldEnd) {
10165                    // Node is entirely past the change range.  We need to move both its pos and
10166                    // end, forward or backward appropriately.
10167                    moveElementEntirelyPastChangeRange(child, /*isArray*/ false, delta, oldText, newText, aggressiveChecks);
10168                    return;
10169                }
10170
10171                // Check if the element intersects the change range.  If it does, then it is not
10172                // reusable.  Also, we'll need to recurse to see what constituent portions we may
10173                // be able to use.
10174                const fullEnd = child.end;
10175                if (fullEnd >= changeStart) {
10176                    child.intersectsChange = true;
10177                    child._children = undefined;
10178
10179                    // Adjust the pos or end (or both) of the intersecting element accordingly.
10180                    adjustIntersectingElement(child, changeStart, changeRangeOldEnd, changeRangeNewEnd, delta);
10181                    forEachChild(child, visitNode, visitArray);
10182                    if (hasJSDocNodes(child)) {
10183                        for (const jsDocComment of child.jsDoc!) {
10184                            visitNode(jsDocComment as Node as IncrementalNode);
10185                        }
10186                    }
10187                    checkNodePositions(child, aggressiveChecks);
10188                    return;
10189                }
10190
10191                // Otherwise, the node is entirely before the change range.  No need to do anything with it.
10192                Debug.assert(fullEnd < changeStart);
10193            }
10194
10195            function visitArray(array: IncrementalNodeArray) {
10196                Debug.assert(array.pos <= array.end);
10197                if (array.pos > changeRangeOldEnd) {
10198                    // Array is entirely after the change range.  We need to move it, and move any of
10199                    // its children.
10200                    moveElementEntirelyPastChangeRange(array, /*isArray*/ true, delta, oldText, newText, aggressiveChecks);
10201                    return;
10202                }
10203
10204                // Check if the element intersects the change range.  If it does, then it is not
10205                // reusable.  Also, we'll need to recurse to see what constituent portions we may
10206                // be able to use.
10207                const fullEnd = array.end;
10208                if (fullEnd >= changeStart) {
10209                    array.intersectsChange = true;
10210                    array._children = undefined;
10211
10212                    // Adjust the pos or end (or both) of the intersecting array accordingly.
10213                    adjustIntersectingElement(array, changeStart, changeRangeOldEnd, changeRangeNewEnd, delta);
10214                    for (const node of array) {
10215                        if (!node.virtual) {
10216                            visitNode(node);
10217                        }
10218                    }
10219                    return;
10220                }
10221
10222                // Otherwise, the array is entirely before the change range.  No need to do anything with it.
10223                Debug.assert(fullEnd < changeStart);
10224            }
10225        }
10226
10227        function extendToAffectedRange(sourceFile: SourceFile, changeRange: TextChangeRange): TextChangeRange {
10228            // Consider the following code:
10229            //      void foo() { /; }
10230            //
10231            // If the text changes with an insertion of / just before the semicolon then we end up with:
10232            //      void foo() { //; }
10233            //
10234            // If we were to just use the changeRange a is, then we would not rescan the { token
10235            // (as it does not intersect the actual original change range).  Because an edit may
10236            // change the token touching it, we actually need to look back *at least* one token so
10237            // that the prior token sees that change.
10238            const maxLookahead = 1;
10239
10240            let start = changeRange.span.start;
10241
10242            // the first iteration aligns us with the change start. subsequent iteration move us to
10243            // the left by maxLookahead tokens.  We only need to do this as long as we're not at the
10244            // start of the tree.
10245            for (let i = 0; start > 0 && i <= maxLookahead; i++) {
10246                const nearestNode = findNearestNodeStartingBeforeOrAtPosition(sourceFile, start);
10247                Debug.assert(nearestNode.pos <= start);
10248                const position = nearestNode.pos;
10249
10250                start = Math.max(0, position - 1);
10251            }
10252
10253            const finalSpan = createTextSpanFromBounds(start, textSpanEnd(changeRange.span));
10254            const finalLength = changeRange.newLength + (changeRange.span.start - start);
10255
10256            return createTextChangeRange(finalSpan, finalLength);
10257        }
10258
10259        function findNearestNodeStartingBeforeOrAtPosition(sourceFile: SourceFile, position: number): Node {
10260            let bestResult: Node = sourceFile;
10261            let lastNodeEntirelyBeforePosition: Node | undefined;
10262
10263            forEachChild(sourceFile, visit);
10264
10265            if (lastNodeEntirelyBeforePosition) {
10266                const lastChildOfLastEntireNodeBeforePosition = getLastDescendant(lastNodeEntirelyBeforePosition);
10267                if (lastChildOfLastEntireNodeBeforePosition.pos > bestResult.pos) {
10268                    bestResult = lastChildOfLastEntireNodeBeforePosition;
10269                }
10270            }
10271
10272            return bestResult;
10273
10274            function getLastDescendant(node: Node): Node {
10275                while (true) {
10276                    const lastChild = getLastChild(node);
10277                    if (lastChild) {
10278                        node = lastChild;
10279                    }
10280                    else {
10281                        return node;
10282                    }
10283                }
10284            }
10285
10286            function visit(child: Node) {
10287                if (nodeIsMissing(child)) {
10288                    // Missing nodes are effectively invisible to us.  We never even consider them
10289                    // When trying to find the nearest node before us.
10290                    return;
10291                }
10292
10293                // If the child intersects this position, then this node is currently the nearest
10294                // node that starts before the position.
10295                if (child.pos <= position) {
10296                    if (child.pos >= bestResult.pos) {
10297                        // This node starts before the position, and is closer to the position than
10298                        // the previous best node we found.  It is now the new best node.
10299                        bestResult = child;
10300                    }
10301
10302                    // Now, the node may overlap the position, or it may end entirely before the
10303                    // position.  If it overlaps with the position, then either it, or one of its
10304                    // children must be the nearest node before the position.  So we can just
10305                    // recurse into this child to see if we can find something better.
10306                    if (position < child.end) {
10307                        // The nearest node is either this child, or one of the children inside
10308                        // of it.  We've already marked this child as the best so far.  Recurse
10309                        // in case one of the children is better.
10310                        forEachChild(child, visit);
10311
10312                        // Once we look at the children of this node, then there's no need to
10313                        // continue any further.
10314                        return true;
10315                    }
10316                    else {
10317                        Debug.assert(child.end <= position);
10318                        // The child ends entirely before this position.  Say you have the following
10319                        // (where $ is the position)
10320                        //
10321                        //      <complex expr 1> ? <complex expr 2> $ : <...> <...>
10322                        //
10323                        // We would want to find the nearest preceding node in "complex expr 2".
10324                        // To support that, we keep track of this node, and once we're done searching
10325                        // for a best node, we recurse down this node to see if we can find a good
10326                        // result in it.
10327                        //
10328                        // This approach allows us to quickly skip over nodes that are entirely
10329                        // before the position, while still allowing us to find any nodes in the
10330                        // last one that might be what we want.
10331                        lastNodeEntirelyBeforePosition = child;
10332                    }
10333                }
10334                else {
10335                    Debug.assert(child.pos > position);
10336                    // We're now at a node that is entirely past the position we're searching for.
10337                    // This node (and all following nodes) could never contribute to the result,
10338                    // so just skip them by returning 'true' here.
10339                    return true;
10340                }
10341            }
10342        }
10343
10344        function checkChangeRange(sourceFile: SourceFile, newText: string, textChangeRange: TextChangeRange, aggressiveChecks: boolean) {
10345            const oldText = sourceFile.text;
10346            if (textChangeRange) {
10347                Debug.assert((oldText.length - textChangeRange.span.length + textChangeRange.newLength) === newText.length);
10348
10349                if (aggressiveChecks || Debug.shouldAssert(AssertionLevel.VeryAggressive)) {
10350                    const oldTextPrefix = oldText.substr(0, textChangeRange.span.start);
10351                    const newTextPrefix = newText.substr(0, textChangeRange.span.start);
10352                    Debug.assert(oldTextPrefix === newTextPrefix);
10353
10354                    const oldTextSuffix = oldText.substring(textSpanEnd(textChangeRange.span), oldText.length);
10355                    const newTextSuffix = newText.substring(textSpanEnd(textChangeRangeNewSpan(textChangeRange)), newText.length);
10356                    Debug.assert(oldTextSuffix === newTextSuffix);
10357                }
10358            }
10359        }
10360
10361        interface IncrementalElement extends ReadonlyTextRange {
10362            readonly parent: Node;
10363            intersectsChange: boolean;
10364            length?: number;
10365            _children: Node[] | undefined;
10366        }
10367
10368        export interface IncrementalNode extends Node, IncrementalElement {
10369            hasBeenIncrementallyParsed: boolean;
10370        }
10371
10372        interface IncrementalNodeArray extends NodeArray<IncrementalNode>, IncrementalElement {
10373            length: number;
10374        }
10375
10376        // Allows finding nodes in the source file at a certain position in an efficient manner.
10377        // The implementation takes advantage of the calling pattern it knows the parser will
10378        // make in order to optimize finding nodes as quickly as possible.
10379        export interface SyntaxCursor {
10380            currentNode(position: number): IncrementalNode;
10381        }
10382
10383        export function createSyntaxCursor(sourceFile: SourceFile): SyntaxCursor {
10384            let currentArray: NodeArray<Node> = sourceFile.statements;
10385            let currentArrayIndex = 0;
10386
10387            Debug.assert(currentArrayIndex < currentArray.length);
10388            let current = currentArray[currentArrayIndex];
10389            let lastQueriedPosition = InvalidPosition.Value;
10390
10391            return {
10392                currentNode(position: number) {
10393                    // Only compute the current node if the position is different than the last time
10394                    // we were asked.  The parser commonly asks for the node at the same position
10395                    // twice.  Once to know if can read an appropriate list element at a certain point,
10396                    // and then to actually read and consume the node.
10397                    if (position !== lastQueriedPosition) {
10398                        // Much of the time the parser will need the very next node in the array that
10399                        // we just returned a node from.So just simply check for that case and move
10400                        // forward in the array instead of searching for the node again.
10401                        if (current && current.end === position && currentArrayIndex < (currentArray.length - 1)) {
10402                            currentArrayIndex++;
10403                            current = currentArray[currentArrayIndex];
10404                        }
10405
10406                        // If we don't have a node, or the node we have isn't in the right position,
10407                        // then try to find a viable node at the position requested.
10408                        if (!current || current.pos !== position) {
10409                            findHighestListElementThatStartsAtPosition(position);
10410                        }
10411                    }
10412
10413                    // Cache this query so that we don't do any extra work if the parser calls back
10414                    // into us.  Note: this is very common as the parser will make pairs of calls like
10415                    // 'isListElement -> parseListElement'.  If we were unable to find a node when
10416                    // called with 'isListElement', we don't want to redo the work when parseListElement
10417                    // is called immediately after.
10418                    lastQueriedPosition = position;
10419
10420                    // Either we don'd have a node, or we have a node at the position being asked for.
10421                    Debug.assert(!current || current.pos === position);
10422                    return current as IncrementalNode;
10423                }
10424            };
10425
10426            // Finds the highest element in the tree we can find that starts at the provided position.
10427            // The element must be a direct child of some node list in the tree.  This way after we
10428            // return it, we can easily return its next sibling in the list.
10429            function findHighestListElementThatStartsAtPosition(position: number) {
10430                // Clear out any cached state about the last node we found.
10431                currentArray = undefined!;
10432                currentArrayIndex = InvalidPosition.Value;
10433                current = undefined!;
10434
10435                // Recurse into the source file to find the highest node at this position.
10436                forEachChild(sourceFile, visitNode, visitArray);
10437                return;
10438
10439                function visitNode(node: Node) {
10440                    if (position >= node.pos && position < node.end) {
10441                        // Position was within this node.  Keep searching deeper to find the node.
10442                        forEachChild(node, visitNode, visitArray);
10443
10444                        // don't proceed any further in the search.
10445                        return true;
10446                    }
10447
10448                    // position wasn't in this node, have to keep searching.
10449                    return false;
10450                }
10451
10452                function visitArray(array: NodeArray<Node>) {
10453                    if (position >= array.pos && position < array.end) {
10454                        // position was in this array.  Search through this array to see if we find a
10455                        // viable element.
10456                        for (let i = 0; i < array.length; i++) {
10457                            const child = array[i];
10458                            if (child) {
10459                                if (child.pos === position) {
10460                                    // Found the right node.  We're done.
10461                                    currentArray = array;
10462                                    currentArrayIndex = i;
10463                                    current = child;
10464                                    return true;
10465                                }
10466                                else {
10467                                    if (child.pos < position && position < child.end) {
10468                                        // Position in somewhere within this child.  Search in it and
10469                                        // stop searching in this array.
10470                                        forEachChild(child, visitNode, visitArray);
10471                                        return true;
10472                                    }
10473                                }
10474                            }
10475                        }
10476                    }
10477
10478                    // position wasn't in this array, have to keep searching.
10479                    return false;
10480                }
10481            }
10482        }
10483
10484        const enum InvalidPosition {
10485            Value = -1
10486        }
10487    }
10488
10489    /** @internal */
10490    export function isDeclarationFileName(fileName: string): boolean {
10491        return fileExtensionIsOneOf(fileName, supportedDeclarationExtensions);
10492    }
10493
10494    /*@internal*/
10495    export interface PragmaContext {
10496        languageVersion: ScriptTarget;
10497        pragmas?: PragmaMap;
10498        checkJsDirective?: CheckJsDirective;
10499        referencedFiles: FileReference[];
10500        typeReferenceDirectives: FileReference[];
10501        libReferenceDirectives: FileReference[];
10502        amdDependencies: AmdDependency[];
10503        hasNoDefaultLib?: boolean;
10504        moduleName?: string;
10505    }
10506
10507    function parseResolutionMode(mode: string | undefined, pos: number, end: number, reportDiagnostic: PragmaDiagnosticReporter): ModuleKind.ESNext | ModuleKind.CommonJS | undefined {
10508        if (!mode) {
10509            return undefined;
10510        }
10511        if (mode === "import") {
10512            return ModuleKind.ESNext;
10513        }
10514        if (mode === "require") {
10515            return ModuleKind.CommonJS;
10516        }
10517        reportDiagnostic(pos, end - pos, Diagnostics.resolution_mode_should_be_either_require_or_import);
10518        return undefined;
10519    }
10520
10521    /*@internal*/
10522    export function processCommentPragmas(context: PragmaContext, sourceText: string): void {
10523        const pragmas: PragmaPseudoMapEntry[] = [];
10524
10525        for (const range of getLeadingCommentRanges(sourceText, 0) || emptyArray) {
10526            const comment = sourceText.substring(range.pos, range.end);
10527            extractPragmas(pragmas, range, comment);
10528        }
10529
10530        context.pragmas = new Map() as PragmaMap;
10531        for (const pragma of pragmas) {
10532            if (context.pragmas.has(pragma.name)) {
10533                const currentValue = context.pragmas.get(pragma.name);
10534                if (currentValue instanceof Array) {
10535                    currentValue.push(pragma.args);
10536                }
10537                else {
10538                    context.pragmas.set(pragma.name, [currentValue, pragma.args]);
10539                }
10540                continue;
10541            }
10542            context.pragmas.set(pragma.name, pragma.args);
10543        }
10544    }
10545
10546    /*@internal*/
10547    type PragmaDiagnosticReporter = (pos: number, length: number, message: DiagnosticMessage) => void;
10548
10549    /*@internal*/
10550    export function processPragmasIntoFields(context: PragmaContext, reportDiagnostic: PragmaDiagnosticReporter): void {
10551        context.checkJsDirective = undefined;
10552        context.referencedFiles = [];
10553        context.typeReferenceDirectives = [];
10554        context.libReferenceDirectives = [];
10555        context.amdDependencies = [];
10556        context.hasNoDefaultLib = false;
10557        context.pragmas!.forEach((entryOrList, key) => { // TODO: GH#18217
10558            // TODO: The below should be strongly type-guarded and not need casts/explicit annotations, since entryOrList is related to
10559            // key and key is constrained to a union; but it's not (see GH#21483 for at least partial fix) :(
10560            switch (key) {
10561                case "reference": {
10562                    const referencedFiles = context.referencedFiles;
10563                    const typeReferenceDirectives = context.typeReferenceDirectives;
10564                    const libReferenceDirectives = context.libReferenceDirectives;
10565                    forEach(toArray(entryOrList) as PragmaPseudoMap["reference"][], arg => {
10566                        const { types, lib, path, ["resolution-mode"]: res } = arg.arguments;
10567                        if (arg.arguments["no-default-lib"]) {
10568                            context.hasNoDefaultLib = true;
10569                        }
10570                        else if (types) {
10571                            const parsed = parseResolutionMode(res, types.pos, types.end, reportDiagnostic);
10572                            typeReferenceDirectives.push({ pos: types.pos, end: types.end, fileName: types.value, ...(parsed ? { resolutionMode: parsed } : {}) });
10573                        }
10574                        else if (lib) {
10575                            libReferenceDirectives.push({ pos: lib.pos, end: lib.end, fileName: lib.value });
10576                        }
10577                        else if (path) {
10578                            referencedFiles.push({ pos: path.pos, end: path.end, fileName: path.value });
10579                        }
10580                        else {
10581                            reportDiagnostic(arg.range.pos, arg.range.end - arg.range.pos, Diagnostics.Invalid_reference_directive_syntax);
10582                        }
10583                    });
10584                    break;
10585                }
10586                case "amd-dependency": {
10587                    context.amdDependencies = map(
10588                        toArray(entryOrList) as PragmaPseudoMap["amd-dependency"][],
10589                        x => ({ name: x.arguments.name, path: x.arguments.path }));
10590                    break;
10591                }
10592                case "amd-module": {
10593                    if (entryOrList instanceof Array) {
10594                        for (const entry of entryOrList) {
10595                            if (context.moduleName) {
10596                                // TODO: It's probably fine to issue this diagnostic on all instances of the pragma
10597                                reportDiagnostic(entry.range.pos, entry.range.end - entry.range.pos, Diagnostics.An_AMD_module_cannot_have_multiple_name_assignments);
10598                            }
10599                            context.moduleName = (entry as PragmaPseudoMap["amd-module"]).arguments.name;
10600                        }
10601                    }
10602                    else {
10603                        context.moduleName = (entryOrList as PragmaPseudoMap["amd-module"]).arguments.name;
10604                    }
10605                    break;
10606                }
10607                case "ts-nocheck":
10608                case "ts-check": {
10609                    // _last_ of either nocheck or check in a file is the "winner"
10610                    forEach(toArray(entryOrList), entry => {
10611                        if (!context.checkJsDirective || entry.range.pos > context.checkJsDirective.pos) {
10612                            context.checkJsDirective = {
10613                                enabled: key === "ts-check",
10614                                end: entry.range.end,
10615                                pos: entry.range.pos
10616                            };
10617                        }
10618                    });
10619                    break;
10620                }
10621                case "jsx":
10622                case "jsxfrag":
10623                case "jsximportsource":
10624                case "jsxruntime":
10625                    return; // Accessed directly
10626                default: Debug.fail("Unhandled pragma kind"); // Can this be made into an assertNever in the future?
10627            }
10628        });
10629    }
10630
10631    const namedArgRegExCache = new Map<string, RegExp>();
10632    function getNamedArgRegEx(name: string): RegExp {
10633        if (namedArgRegExCache.has(name)) {
10634            return namedArgRegExCache.get(name)!;
10635        }
10636        const result = new RegExp(`(\\s${name}\\s*=\\s*)(?:(?:'([^']*)')|(?:"([^"]*)"))`, "im");
10637        namedArgRegExCache.set(name, result);
10638        return result;
10639    }
10640
10641    const tripleSlashXMLCommentStartRegEx = /^\/\/\/\s*<(\S+)\s.*?\/>/im;
10642    const singleLinePragmaRegEx = /^\/\/\/?\s*@(\S+)\s*(.*)\s*$/im;
10643    function extractPragmas(pragmas: PragmaPseudoMapEntry[], range: CommentRange, text: string) {
10644        const tripleSlash = range.kind === SyntaxKind.SingleLineCommentTrivia && tripleSlashXMLCommentStartRegEx.exec(text);
10645        if (tripleSlash) {
10646            const name = tripleSlash[1].toLowerCase() as keyof PragmaPseudoMap; // Technically unsafe cast, but we do it so the below check to make it safe typechecks
10647            const pragma = commentPragmas[name] as PragmaDefinition;
10648            if (!pragma || !(pragma.kind! & PragmaKindFlags.TripleSlashXML)) {
10649                return;
10650            }
10651            if (pragma.args) {
10652                const argument: {[index: string]: string | {value: string, pos: number, end: number}} = {};
10653                for (const arg of pragma.args) {
10654                    const matcher = getNamedArgRegEx(arg.name);
10655                    const matchResult = matcher.exec(text);
10656                    if (!matchResult && !arg.optional) {
10657                        return; // Missing required argument, don't parse
10658                    }
10659                    else if (matchResult) {
10660                        const value = matchResult[2] || matchResult[3];
10661                        if (arg.captureSpan) {
10662                            const startPos = range.pos + matchResult.index + matchResult[1].length + 1;
10663                            argument[arg.name] = {
10664                                value,
10665                                pos: startPos,
10666                                end: startPos + value.length
10667                            };
10668                        }
10669                        else {
10670                            argument[arg.name] = value;
10671                        }
10672                    }
10673                }
10674                pragmas.push({ name, args: { arguments: argument, range } } as PragmaPseudoMapEntry);
10675            }
10676            else {
10677                pragmas.push({ name, args: { arguments: {}, range } } as PragmaPseudoMapEntry);
10678            }
10679            return;
10680        }
10681
10682        const singleLine = range.kind === SyntaxKind.SingleLineCommentTrivia && singleLinePragmaRegEx.exec(text);
10683        if (singleLine) {
10684            return addPragmaForMatch(pragmas, range, PragmaKindFlags.SingleLine, singleLine);
10685        }
10686
10687        if (range.kind === SyntaxKind.MultiLineCommentTrivia) {
10688            const multiLinePragmaRegEx = /@(\S+)(\s+.*)?$/gim; // Defined inline since it uses the "g" flag, which keeps a persistent index (for iterating)
10689            let multiLineMatch: RegExpExecArray | null;
10690            while (multiLineMatch = multiLinePragmaRegEx.exec(text)) {
10691                addPragmaForMatch(pragmas, range, PragmaKindFlags.MultiLine, multiLineMatch);
10692            }
10693        }
10694    }
10695
10696    function addPragmaForMatch(pragmas: PragmaPseudoMapEntry[], range: CommentRange, kind: PragmaKindFlags, match: RegExpExecArray) {
10697        if (!match) return;
10698        const name = match[1].toLowerCase() as keyof PragmaPseudoMap; // Technically unsafe cast, but we do it so they below check to make it safe typechecks
10699        const pragma = commentPragmas[name] as PragmaDefinition;
10700        if (!pragma || !(pragma.kind! & kind)) {
10701            return;
10702        }
10703        const args = match[2]; // Split on spaces and match up positionally with definition
10704        const argument = getNamedPragmaArguments(pragma, args);
10705        if (argument === "fail") return; // Missing required argument, fail to parse it
10706        pragmas.push({ name, args: { arguments: argument, range } } as PragmaPseudoMapEntry);
10707        return;
10708    }
10709
10710    function getNamedPragmaArguments(pragma: PragmaDefinition, text: string | undefined): {[index: string]: string} | "fail" {
10711        if (!text) return {};
10712        if (!pragma.args) return {};
10713        const args = trimString(text).split(/\s+/);
10714        const argMap: {[index: string]: string} = {};
10715        for (let i = 0; i < pragma.args.length; i++) {
10716            const argument = pragma.args[i];
10717            if (!args[i] && !argument.optional) {
10718                return "fail";
10719            }
10720            if (argument.captureSpan) {
10721                return Debug.fail("Capture spans not yet implemented for non-xml pragmas");
10722            }
10723            argMap[argument.name] = args[i];
10724        }
10725        return argMap;
10726    }
10727
10728    /** @internal */
10729    export function tagNamesAreEquivalent(lhs: JsxTagNameExpression, rhs: JsxTagNameExpression): boolean {
10730        if (lhs.kind !== rhs.kind) {
10731            return false;
10732        }
10733
10734        if (lhs.kind === SyntaxKind.Identifier) {
10735            return lhs.escapedText === (rhs as Identifier).escapedText;
10736        }
10737
10738        if (lhs.kind === SyntaxKind.ThisKeyword) {
10739            return true;
10740        }
10741
10742        // If we are at this statement then we must have PropertyAccessExpression and because tag name in Jsx element can only
10743        // take forms of JsxTagNameExpression which includes an identifier, "this" expression, or another propertyAccessExpression
10744        // it is safe to case the expression property as such. See parseJsxElementName for how we parse tag name in Jsx element
10745        return (lhs as PropertyAccessExpression).name.escapedText === (rhs as PropertyAccessExpression).name.escapedText &&
10746            tagNamesAreEquivalent((lhs as PropertyAccessExpression).expression as JsxTagNameExpression, (rhs as PropertyAccessExpression).expression as JsxTagNameExpression);
10747    }
10748}
10749