• 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    /**
64     * Invokes a callback for each child of the given node. The 'cbNode' callback is invoked for all child nodes
65     * stored in properties. If a 'cbNodes' callback is specified, it is invoked for embedded arrays; otherwise,
66     * embedded arrays are flattened and the 'cbNode' callback is invoked for each element. If a callback returns
67     * a truthy value, iteration stops and that value is returned. Otherwise, undefined is returned.
68     *
69     * @param node a given node to visit its children
70     * @param cbNode a callback to be invoked for all child nodes
71     * @param cbNodes a callback to be invoked for embedded array
72     *
73     * @remarks `forEachChild` must visit the children of a node in the order
74     * that they appear in the source code. The language service depends on this property to locate nodes by position.
75     */
76    export function forEachChild<T>(node: Node, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray<Node>) => T | undefined): T | undefined {
77        if (!node || node.kind <= SyntaxKind.LastToken) {
78            return;
79        }
80        switch (node.kind) {
81            case SyntaxKind.QualifiedName:
82                return visitNode(cbNode, (<QualifiedName>node).left) ||
83                    visitNode(cbNode, (<QualifiedName>node).right);
84            case SyntaxKind.TypeParameter:
85                return visitNode(cbNode, (<TypeParameterDeclaration>node).name) ||
86                    visitNode(cbNode, (<TypeParameterDeclaration>node).constraint) ||
87                    visitNode(cbNode, (<TypeParameterDeclaration>node).default) ||
88                    visitNode(cbNode, (<TypeParameterDeclaration>node).expression);
89            case SyntaxKind.ShorthandPropertyAssignment:
90                return visitNodes(cbNode, cbNodes, node.decorators) ||
91                    visitNodes(cbNode, cbNodes, node.modifiers) ||
92                    visitNode(cbNode, (<ShorthandPropertyAssignment>node).name) ||
93                    visitNode(cbNode, (<ShorthandPropertyAssignment>node).questionToken) ||
94                    visitNode(cbNode, (<ShorthandPropertyAssignment>node).exclamationToken) ||
95                    visitNode(cbNode, (<ShorthandPropertyAssignment>node).equalsToken) ||
96                    visitNode(cbNode, (<ShorthandPropertyAssignment>node).objectAssignmentInitializer);
97            case SyntaxKind.SpreadAssignment:
98                return visitNode(cbNode, (<SpreadAssignment>node).expression);
99            case SyntaxKind.Parameter:
100                return visitNodes(cbNode, cbNodes, node.decorators) ||
101                    visitNodes(cbNode, cbNodes, node.modifiers) ||
102                    visitNode(cbNode, (<ParameterDeclaration>node).dotDotDotToken) ||
103                    visitNode(cbNode, (<ParameterDeclaration>node).name) ||
104                    visitNode(cbNode, (<ParameterDeclaration>node).questionToken) ||
105                    visitNode(cbNode, (<ParameterDeclaration>node).type) ||
106                    visitNode(cbNode, (<ParameterDeclaration>node).initializer);
107            case SyntaxKind.PropertyDeclaration:
108                return visitNodes(cbNode, cbNodes, node.decorators) ||
109                    visitNodes(cbNode, cbNodes, node.modifiers) ||
110                    visitNode(cbNode, (<PropertyDeclaration>node).name) ||
111                    visitNode(cbNode, (<PropertyDeclaration>node).questionToken) ||
112                    visitNode(cbNode, (<PropertyDeclaration>node).exclamationToken) ||
113                    visitNode(cbNode, (<PropertyDeclaration>node).type) ||
114                    visitNode(cbNode, (<PropertyDeclaration>node).initializer);
115            case SyntaxKind.PropertySignature:
116                return visitNodes(cbNode, cbNodes, node.decorators) ||
117                    visitNodes(cbNode, cbNodes, node.modifiers) ||
118                    visitNode(cbNode, (<PropertySignature>node).name) ||
119                    visitNode(cbNode, (<PropertySignature>node).questionToken) ||
120                    visitNode(cbNode, (<PropertySignature>node).type) ||
121                    visitNode(cbNode, (<PropertySignature>node).initializer);
122            case SyntaxKind.PropertyAssignment:
123                return visitNodes(cbNode, cbNodes, node.decorators) ||
124                    visitNodes(cbNode, cbNodes, node.modifiers) ||
125                    visitNode(cbNode, (<PropertyAssignment>node).name) ||
126                    visitNode(cbNode, (<PropertyAssignment>node).questionToken) ||
127                    visitNode(cbNode, (<PropertyAssignment>node).initializer);
128            case SyntaxKind.VariableDeclaration:
129                return visitNodes(cbNode, cbNodes, node.decorators) ||
130                    visitNodes(cbNode, cbNodes, node.modifiers) ||
131                    visitNode(cbNode, (<VariableDeclaration>node).name) ||
132                    visitNode(cbNode, (<VariableDeclaration>node).exclamationToken) ||
133                    visitNode(cbNode, (<VariableDeclaration>node).type) ||
134                    visitNode(cbNode, (<VariableDeclaration>node).initializer);
135            case SyntaxKind.BindingElement:
136                return visitNodes(cbNode, cbNodes, node.decorators) ||
137                    visitNodes(cbNode, cbNodes, node.modifiers) ||
138                    visitNode(cbNode, (<BindingElement>node).dotDotDotToken) ||
139                    visitNode(cbNode, (<BindingElement>node).propertyName) ||
140                    visitNode(cbNode, (<BindingElement>node).name) ||
141                    visitNode(cbNode, (<BindingElement>node).initializer);
142            case SyntaxKind.FunctionType:
143            case SyntaxKind.ConstructorType:
144            case SyntaxKind.CallSignature:
145            case SyntaxKind.ConstructSignature:
146            case SyntaxKind.IndexSignature:
147                return visitNodes(cbNode, cbNodes, node.decorators) ||
148                    visitNodes(cbNode, cbNodes, node.modifiers) ||
149                    visitNodes(cbNode, cbNodes, (<SignatureDeclaration>node).typeParameters) ||
150                    visitNodes(cbNode, cbNodes, (<SignatureDeclaration>node).parameters) ||
151                    visitNode(cbNode, (<SignatureDeclaration>node).type);
152            case SyntaxKind.EtsComponentExpression:
153                return visitNode(cbNode, (<EtsComponentExpression>node).expression) ||
154                    visitNodes(cbNode, cbNodes, (<EtsComponentExpression>node).arguments) ||
155                    visitNode(cbNode, (<EtsComponentExpression>node).body);
156            case SyntaxKind.MethodDeclaration:
157            case SyntaxKind.MethodSignature:
158            case SyntaxKind.Constructor:
159            case SyntaxKind.GetAccessor:
160            case SyntaxKind.SetAccessor:
161            case SyntaxKind.FunctionExpression:
162            case SyntaxKind.FunctionDeclaration:
163            case SyntaxKind.ArrowFunction:
164                return visitNodes(cbNode, cbNodes, node.decorators) ||
165                    visitNodes(cbNode, cbNodes, node.modifiers) ||
166                    visitNode(cbNode, (<FunctionLikeDeclaration>node).asteriskToken) ||
167                    visitNode(cbNode, (<FunctionLikeDeclaration>node).name) ||
168                    visitNode(cbNode, (<FunctionLikeDeclaration>node).questionToken) ||
169                    visitNode(cbNode, (<FunctionLikeDeclaration>node).exclamationToken) ||
170                    visitNodes(cbNode, cbNodes, (<FunctionLikeDeclaration>node).typeParameters) ||
171                    visitNodes(cbNode, cbNodes, (<FunctionLikeDeclaration>node).parameters) ||
172                    visitNode(cbNode, (<FunctionLikeDeclaration>node).type) ||
173                    visitNode(cbNode, (<ArrowFunction>node).equalsGreaterThanToken) ||
174                    visitNode(cbNode, (<FunctionLikeDeclaration>node).body);
175            case SyntaxKind.TypeReference:
176                return visitNode(cbNode, (<TypeReferenceNode>node).typeName) ||
177                    visitNodes(cbNode, cbNodes, (<TypeReferenceNode>node).typeArguments);
178            case SyntaxKind.TypePredicate:
179                return visitNode(cbNode, (<TypePredicateNode>node).assertsModifier) ||
180                    visitNode(cbNode, (<TypePredicateNode>node).parameterName) ||
181                    visitNode(cbNode, (<TypePredicateNode>node).type);
182            case SyntaxKind.TypeQuery:
183                return visitNode(cbNode, (<TypeQueryNode>node).exprName);
184            case SyntaxKind.TypeLiteral:
185                return visitNodes(cbNode, cbNodes, (<TypeLiteralNode>node).members);
186            case SyntaxKind.ArrayType:
187                return visitNode(cbNode, (<ArrayTypeNode>node).elementType);
188            case SyntaxKind.TupleType:
189                return visitNodes(cbNode, cbNodes, (<TupleTypeNode>node).elements);
190            case SyntaxKind.UnionType:
191            case SyntaxKind.IntersectionType:
192                return visitNodes(cbNode, cbNodes, (<UnionOrIntersectionTypeNode>node).types);
193            case SyntaxKind.ConditionalType:
194                return visitNode(cbNode, (<ConditionalTypeNode>node).checkType) ||
195                    visitNode(cbNode, (<ConditionalTypeNode>node).extendsType) ||
196                    visitNode(cbNode, (<ConditionalTypeNode>node).trueType) ||
197                    visitNode(cbNode, (<ConditionalTypeNode>node).falseType);
198            case SyntaxKind.InferType:
199                return visitNode(cbNode, (<InferTypeNode>node).typeParameter);
200            case SyntaxKind.ImportType:
201                return visitNode(cbNode, (<ImportTypeNode>node).argument) ||
202                    visitNode(cbNode, (<ImportTypeNode>node).qualifier) ||
203                    visitNodes(cbNode, cbNodes, (<ImportTypeNode>node).typeArguments);
204            case SyntaxKind.ParenthesizedType:
205            case SyntaxKind.TypeOperator:
206                return visitNode(cbNode, (<ParenthesizedTypeNode | TypeOperatorNode>node).type);
207            case SyntaxKind.IndexedAccessType:
208                return visitNode(cbNode, (<IndexedAccessTypeNode>node).objectType) ||
209                    visitNode(cbNode, (<IndexedAccessTypeNode>node).indexType);
210            case SyntaxKind.MappedType:
211                return visitNode(cbNode, (<MappedTypeNode>node).readonlyToken) ||
212                    visitNode(cbNode, (<MappedTypeNode>node).typeParameter) ||
213                    visitNode(cbNode, (<MappedTypeNode>node).nameType) ||
214                    visitNode(cbNode, (<MappedTypeNode>node).questionToken) ||
215                    visitNode(cbNode, (<MappedTypeNode>node).type);
216            case SyntaxKind.LiteralType:
217                return visitNode(cbNode, (<LiteralTypeNode>node).literal);
218            case SyntaxKind.NamedTupleMember:
219                return visitNode(cbNode, (<NamedTupleMember>node).dotDotDotToken) ||
220                    visitNode(cbNode, (<NamedTupleMember>node).name) ||
221                    visitNode(cbNode, (<NamedTupleMember>node).questionToken) ||
222                    visitNode(cbNode, (<NamedTupleMember>node).type);
223            case SyntaxKind.ObjectBindingPattern:
224            case SyntaxKind.ArrayBindingPattern:
225                return visitNodes(cbNode, cbNodes, (<BindingPattern>node).elements);
226            case SyntaxKind.ArrayLiteralExpression:
227                return visitNodes(cbNode, cbNodes, (<ArrayLiteralExpression>node).elements);
228            case SyntaxKind.ObjectLiteralExpression:
229                return visitNodes(cbNode, cbNodes, (<ObjectLiteralExpression>node).properties);
230            case SyntaxKind.PropertyAccessExpression:
231                return visitNode(cbNode, (<PropertyAccessExpression>node).expression) ||
232                    visitNode(cbNode, (<PropertyAccessExpression>node).questionDotToken) ||
233                    visitNode(cbNode, (<PropertyAccessExpression>node).name);
234            case SyntaxKind.ElementAccessExpression:
235                return visitNode(cbNode, (<ElementAccessExpression>node).expression) ||
236                    visitNode(cbNode, (<ElementAccessExpression>node).questionDotToken) ||
237                    visitNode(cbNode, (<ElementAccessExpression>node).argumentExpression);
238            case SyntaxKind.CallExpression:
239            case SyntaxKind.NewExpression:
240                return visitNode(cbNode, (<CallExpression>node).expression) ||
241                    visitNode(cbNode, (<CallExpression>node).questionDotToken) ||
242                    visitNodes(cbNode, cbNodes, (<CallExpression>node).typeArguments) ||
243                    visitNodes(cbNode, cbNodes, (<CallExpression>node).arguments);
244            case SyntaxKind.TaggedTemplateExpression:
245                return visitNode(cbNode, (<TaggedTemplateExpression>node).tag) ||
246                    visitNode(cbNode, (<TaggedTemplateExpression>node).questionDotToken) ||
247                    visitNodes(cbNode, cbNodes, (<TaggedTemplateExpression>node).typeArguments) ||
248                    visitNode(cbNode, (<TaggedTemplateExpression>node).template);
249            case SyntaxKind.TypeAssertionExpression:
250                return visitNode(cbNode, (<TypeAssertion>node).type) ||
251                    visitNode(cbNode, (<TypeAssertion>node).expression);
252            case SyntaxKind.ParenthesizedExpression:
253                return visitNode(cbNode, (<ParenthesizedExpression>node).expression);
254            case SyntaxKind.DeleteExpression:
255                return visitNode(cbNode, (<DeleteExpression>node).expression);
256            case SyntaxKind.TypeOfExpression:
257                return visitNode(cbNode, (<TypeOfExpression>node).expression);
258            case SyntaxKind.VoidExpression:
259                return visitNode(cbNode, (<VoidExpression>node).expression);
260            case SyntaxKind.PrefixUnaryExpression:
261                return visitNode(cbNode, (<PrefixUnaryExpression>node).operand);
262            case SyntaxKind.YieldExpression:
263                return visitNode(cbNode, (<YieldExpression>node).asteriskToken) ||
264                    visitNode(cbNode, (<YieldExpression>node).expression);
265            case SyntaxKind.AwaitExpression:
266                return visitNode(cbNode, (<AwaitExpression>node).expression);
267            case SyntaxKind.PostfixUnaryExpression:
268                return visitNode(cbNode, (<PostfixUnaryExpression>node).operand);
269            case SyntaxKind.BinaryExpression:
270                return visitNode(cbNode, (<BinaryExpression>node).left) ||
271                    visitNode(cbNode, (<BinaryExpression>node).operatorToken) ||
272                    visitNode(cbNode, (<BinaryExpression>node).right);
273            case SyntaxKind.AsExpression:
274                return visitNode(cbNode, (<AsExpression>node).expression) ||
275                    visitNode(cbNode, (<AsExpression>node).type);
276            case SyntaxKind.NonNullExpression:
277                return visitNode(cbNode, (<NonNullExpression>node).expression);
278            case SyntaxKind.MetaProperty:
279                return visitNode(cbNode, (<MetaProperty>node).name);
280            case SyntaxKind.ConditionalExpression:
281                return visitNode(cbNode, (<ConditionalExpression>node).condition) ||
282                    visitNode(cbNode, (<ConditionalExpression>node).questionToken) ||
283                    visitNode(cbNode, (<ConditionalExpression>node).whenTrue) ||
284                    visitNode(cbNode, (<ConditionalExpression>node).colonToken) ||
285                    visitNode(cbNode, (<ConditionalExpression>node).whenFalse);
286            case SyntaxKind.SpreadElement:
287                return visitNode(cbNode, (<SpreadElement>node).expression);
288            case SyntaxKind.Block:
289            case SyntaxKind.ModuleBlock:
290                return visitNodes(cbNode, cbNodes, (<Block>node).statements);
291            case SyntaxKind.SourceFile:
292                return visitNodes(cbNode, cbNodes, (<SourceFile>node).statements) ||
293                    visitNode(cbNode, (<SourceFile>node).endOfFileToken);
294            case SyntaxKind.VariableStatement:
295                return visitNodes(cbNode, cbNodes, node.decorators) ||
296                    visitNodes(cbNode, cbNodes, node.modifiers) ||
297                    visitNode(cbNode, (<VariableStatement>node).declarationList);
298            case SyntaxKind.VariableDeclarationList:
299                return visitNodes(cbNode, cbNodes, (<VariableDeclarationList>node).declarations);
300            case SyntaxKind.ExpressionStatement:
301                return visitNode(cbNode, (<ExpressionStatement>node).expression);
302            case SyntaxKind.IfStatement:
303                return visitNode(cbNode, (<IfStatement>node).expression) ||
304                    visitNode(cbNode, (<IfStatement>node).thenStatement) ||
305                    visitNode(cbNode, (<IfStatement>node).elseStatement);
306            case SyntaxKind.DoStatement:
307                return visitNode(cbNode, (<DoStatement>node).statement) ||
308                    visitNode(cbNode, (<DoStatement>node).expression);
309            case SyntaxKind.WhileStatement:
310                return visitNode(cbNode, (<WhileStatement>node).expression) ||
311                    visitNode(cbNode, (<WhileStatement>node).statement);
312            case SyntaxKind.ForStatement:
313                return visitNode(cbNode, (<ForStatement>node).initializer) ||
314                    visitNode(cbNode, (<ForStatement>node).condition) ||
315                    visitNode(cbNode, (<ForStatement>node).incrementor) ||
316                    visitNode(cbNode, (<ForStatement>node).statement);
317            case SyntaxKind.ForInStatement:
318                return visitNode(cbNode, (<ForInStatement>node).initializer) ||
319                    visitNode(cbNode, (<ForInStatement>node).expression) ||
320                    visitNode(cbNode, (<ForInStatement>node).statement);
321            case SyntaxKind.ForOfStatement:
322                return visitNode(cbNode, (<ForOfStatement>node).awaitModifier) ||
323                    visitNode(cbNode, (<ForOfStatement>node).initializer) ||
324                    visitNode(cbNode, (<ForOfStatement>node).expression) ||
325                    visitNode(cbNode, (<ForOfStatement>node).statement);
326            case SyntaxKind.ContinueStatement:
327            case SyntaxKind.BreakStatement:
328                return visitNode(cbNode, (<BreakOrContinueStatement>node).label);
329            case SyntaxKind.ReturnStatement:
330                return visitNode(cbNode, (<ReturnStatement>node).expression);
331            case SyntaxKind.WithStatement:
332                return visitNode(cbNode, (<WithStatement>node).expression) ||
333                    visitNode(cbNode, (<WithStatement>node).statement);
334            case SyntaxKind.SwitchStatement:
335                return visitNode(cbNode, (<SwitchStatement>node).expression) ||
336                    visitNode(cbNode, (<SwitchStatement>node).caseBlock);
337            case SyntaxKind.CaseBlock:
338                return visitNodes(cbNode, cbNodes, (<CaseBlock>node).clauses);
339            case SyntaxKind.CaseClause:
340                return visitNode(cbNode, (<CaseClause>node).expression) ||
341                    visitNodes(cbNode, cbNodes, (<CaseClause>node).statements);
342            case SyntaxKind.DefaultClause:
343                return visitNodes(cbNode, cbNodes, (<DefaultClause>node).statements);
344            case SyntaxKind.LabeledStatement:
345                return visitNode(cbNode, (<LabeledStatement>node).label) ||
346                    visitNode(cbNode, (<LabeledStatement>node).statement);
347            case SyntaxKind.ThrowStatement:
348                return visitNode(cbNode, (<ThrowStatement>node).expression);
349            case SyntaxKind.TryStatement:
350                return visitNode(cbNode, (<TryStatement>node).tryBlock) ||
351                    visitNode(cbNode, (<TryStatement>node).catchClause) ||
352                    visitNode(cbNode, (<TryStatement>node).finallyBlock);
353            case SyntaxKind.CatchClause:
354                return visitNode(cbNode, (<CatchClause>node).variableDeclaration) ||
355                    visitNode(cbNode, (<CatchClause>node).block);
356            case SyntaxKind.Decorator:
357                return visitNode(cbNode, (<Decorator>node).expression);
358            case SyntaxKind.StructDeclaration:
359            case SyntaxKind.ClassDeclaration:
360            case SyntaxKind.ClassExpression:
361                return visitNodes(cbNode, cbNodes, node.decorators) ||
362                    visitNodes(cbNode, cbNodes, node.modifiers) ||
363                    visitNode(cbNode, (<ClassLikeDeclaration>node).name) ||
364                    visitNodes(cbNode, cbNodes, (<ClassLikeDeclaration>node).typeParameters) ||
365                    visitNodes(cbNode, cbNodes, (<ClassLikeDeclaration>node).heritageClauses) ||
366                    visitNodes(cbNode, cbNodes, (<ClassLikeDeclaration>node).members);
367            case SyntaxKind.InterfaceDeclaration:
368                return visitNodes(cbNode, cbNodes, node.decorators) ||
369                    visitNodes(cbNode, cbNodes, node.modifiers) ||
370                    visitNode(cbNode, (<InterfaceDeclaration>node).name) ||
371                    visitNodes(cbNode, cbNodes, (<InterfaceDeclaration>node).typeParameters) ||
372                    visitNodes(cbNode, cbNodes, (<ClassDeclaration>node).heritageClauses) ||
373                    visitNodes(cbNode, cbNodes, (<InterfaceDeclaration>node).members);
374            case SyntaxKind.TypeAliasDeclaration:
375                return visitNodes(cbNode, cbNodes, node.decorators) ||
376                    visitNodes(cbNode, cbNodes, node.modifiers) ||
377                    visitNode(cbNode, (<TypeAliasDeclaration>node).name) ||
378                    visitNodes(cbNode, cbNodes, (<TypeAliasDeclaration>node).typeParameters) ||
379                    visitNode(cbNode, (<TypeAliasDeclaration>node).type);
380            case SyntaxKind.EnumDeclaration:
381                return visitNodes(cbNode, cbNodes, node.decorators) ||
382                    visitNodes(cbNode, cbNodes, node.modifiers) ||
383                    visitNode(cbNode, (<EnumDeclaration>node).name) ||
384                    visitNodes(cbNode, cbNodes, (<EnumDeclaration>node).members);
385            case SyntaxKind.EnumMember:
386                return visitNode(cbNode, (<EnumMember>node).name) ||
387                    visitNode(cbNode, (<EnumMember>node).initializer);
388            case SyntaxKind.ModuleDeclaration:
389                return visitNodes(cbNode, cbNodes, node.decorators) ||
390                    visitNodes(cbNode, cbNodes, node.modifiers) ||
391                    visitNode(cbNode, (<ModuleDeclaration>node).name) ||
392                    visitNode(cbNode, (<ModuleDeclaration>node).body);
393            case SyntaxKind.ImportEqualsDeclaration:
394                return visitNodes(cbNode, cbNodes, node.decorators) ||
395                    visitNodes(cbNode, cbNodes, node.modifiers) ||
396                    visitNode(cbNode, (<ImportEqualsDeclaration>node).name) ||
397                    visitNode(cbNode, (<ImportEqualsDeclaration>node).moduleReference);
398            case SyntaxKind.ImportDeclaration:
399                return visitNodes(cbNode, cbNodes, node.decorators) ||
400                    visitNodes(cbNode, cbNodes, node.modifiers) ||
401                    visitNode(cbNode, (<ImportDeclaration>node).importClause) ||
402                    visitNode(cbNode, (<ImportDeclaration>node).moduleSpecifier);
403            case SyntaxKind.ImportClause:
404                return visitNode(cbNode, (<ImportClause>node).name) ||
405                    visitNode(cbNode, (<ImportClause>node).namedBindings);
406            case SyntaxKind.NamespaceExportDeclaration:
407                return visitNode(cbNode, (<NamespaceExportDeclaration>node).name);
408
409            case SyntaxKind.NamespaceImport:
410                return visitNode(cbNode, (<NamespaceImport>node).name);
411            case SyntaxKind.NamespaceExport:
412                return visitNode(cbNode, (<NamespaceExport>node).name);
413            case SyntaxKind.NamedImports:
414            case SyntaxKind.NamedExports:
415                return visitNodes(cbNode, cbNodes, (<NamedImportsOrExports>node).elements);
416            case SyntaxKind.ExportDeclaration:
417                return visitNodes(cbNode, cbNodes, node.decorators) ||
418                    visitNodes(cbNode, cbNodes, node.modifiers) ||
419                    visitNode(cbNode, (<ExportDeclaration>node).exportClause) ||
420                    visitNode(cbNode, (<ExportDeclaration>node).moduleSpecifier);
421            case SyntaxKind.ImportSpecifier:
422            case SyntaxKind.ExportSpecifier:
423                return visitNode(cbNode, (<ImportOrExportSpecifier>node).propertyName) ||
424                    visitNode(cbNode, (<ImportOrExportSpecifier>node).name);
425            case SyntaxKind.ExportAssignment:
426                return visitNodes(cbNode, cbNodes, node.decorators) ||
427                    visitNodes(cbNode, cbNodes, node.modifiers) ||
428                    visitNode(cbNode, (<ExportAssignment>node).expression);
429            case SyntaxKind.TemplateExpression:
430                return visitNode(cbNode, (<TemplateExpression>node).head) || visitNodes(cbNode, cbNodes, (<TemplateExpression>node).templateSpans);
431            case SyntaxKind.TemplateSpan:
432                return visitNode(cbNode, (<TemplateSpan>node).expression) || visitNode(cbNode, (<TemplateSpan>node).literal);
433            case SyntaxKind.TemplateLiteralType:
434                return visitNode(cbNode, (<TemplateLiteralTypeNode>node).head) || visitNodes(cbNode, cbNodes, (<TemplateLiteralTypeNode>node).templateSpans);
435            case SyntaxKind.TemplateLiteralTypeSpan:
436                return visitNode(cbNode, (<TemplateLiteralTypeSpan>node).type) || visitNode(cbNode, (<TemplateLiteralTypeSpan>node).literal);
437            case SyntaxKind.ComputedPropertyName:
438                return visitNode(cbNode, (<ComputedPropertyName>node).expression);
439            case SyntaxKind.HeritageClause:
440                return visitNodes(cbNode, cbNodes, (<HeritageClause>node).types);
441            case SyntaxKind.ExpressionWithTypeArguments:
442                return visitNode(cbNode, (<ExpressionWithTypeArguments>node).expression) ||
443                    visitNodes(cbNode, cbNodes, (<ExpressionWithTypeArguments>node).typeArguments);
444            case SyntaxKind.ExternalModuleReference:
445                return visitNode(cbNode, (<ExternalModuleReference>node).expression);
446            case SyntaxKind.MissingDeclaration:
447                return visitNodes(cbNode, cbNodes, node.decorators);
448            case SyntaxKind.CommaListExpression:
449                return visitNodes(cbNode, cbNodes, (<CommaListExpression>node).elements);
450
451            case SyntaxKind.JsxElement:
452                return visitNode(cbNode, (<JsxElement>node).openingElement) ||
453                    visitNodes(cbNode, cbNodes, (<JsxElement>node).children) ||
454                    visitNode(cbNode, (<JsxElement>node).closingElement);
455            case SyntaxKind.JsxFragment:
456                return visitNode(cbNode, (<JsxFragment>node).openingFragment) ||
457                    visitNodes(cbNode, cbNodes, (<JsxFragment>node).children) ||
458                    visitNode(cbNode, (<JsxFragment>node).closingFragment);
459            case SyntaxKind.JsxSelfClosingElement:
460            case SyntaxKind.JsxOpeningElement:
461                return visitNode(cbNode, (<JsxOpeningLikeElement>node).tagName) ||
462                    visitNodes(cbNode, cbNodes, (<JsxOpeningLikeElement>node).typeArguments) ||
463                    visitNode(cbNode, (<JsxOpeningLikeElement>node).attributes);
464            case SyntaxKind.JsxAttributes:
465                return visitNodes(cbNode, cbNodes, (<JsxAttributes>node).properties);
466            case SyntaxKind.JsxAttribute:
467                return visitNode(cbNode, (<JsxAttribute>node).name) ||
468                    visitNode(cbNode, (<JsxAttribute>node).initializer);
469            case SyntaxKind.JsxSpreadAttribute:
470                return visitNode(cbNode, (<JsxSpreadAttribute>node).expression);
471            case SyntaxKind.JsxExpression:
472                return visitNode(cbNode, (node as JsxExpression).dotDotDotToken) ||
473                    visitNode(cbNode, (node as JsxExpression).expression);
474            case SyntaxKind.JsxClosingElement:
475                return visitNode(cbNode, (<JsxClosingElement>node).tagName);
476
477            case SyntaxKind.OptionalType:
478            case SyntaxKind.RestType:
479            case SyntaxKind.JSDocTypeExpression:
480            case SyntaxKind.JSDocNonNullableType:
481            case SyntaxKind.JSDocNullableType:
482            case SyntaxKind.JSDocOptionalType:
483            case SyntaxKind.JSDocVariadicType:
484                return visitNode(cbNode, (<OptionalTypeNode | RestTypeNode | JSDocTypeExpression | JSDocTypeReferencingNode>node).type);
485            case SyntaxKind.JSDocFunctionType:
486                return visitNodes(cbNode, cbNodes, (<JSDocFunctionType>node).parameters) ||
487                    visitNode(cbNode, (<JSDocFunctionType>node).type);
488            case SyntaxKind.JSDocComment:
489                return visitNodes(cbNode, cbNodes, (<JSDoc>node).tags);
490            case SyntaxKind.JSDocSeeTag:
491                return visitNode(cbNode, (node as JSDocSeeTag).tagName) ||
492                    visitNode(cbNode, (node as JSDocSeeTag).name);
493            case SyntaxKind.JSDocNameReference:
494                return visitNode(cbNode, (node as JSDocNameReference).name);
495            case SyntaxKind.JSDocParameterTag:
496            case SyntaxKind.JSDocPropertyTag:
497                return visitNode(cbNode, (node as JSDocTag).tagName) ||
498                    ((node as JSDocPropertyLikeTag).isNameFirst
499                        ? visitNode(cbNode, (<JSDocPropertyLikeTag>node).name) ||
500                            visitNode(cbNode, (<JSDocPropertyLikeTag>node).typeExpression)
501                        : visitNode(cbNode, (<JSDocPropertyLikeTag>node).typeExpression) ||
502                            visitNode(cbNode, (<JSDocPropertyLikeTag>node).name));
503            case SyntaxKind.JSDocAuthorTag:
504                return visitNode(cbNode, (node as JSDocTag).tagName);
505            case SyntaxKind.JSDocImplementsTag:
506                return visitNode(cbNode, (node as JSDocTag).tagName) ||
507                    visitNode(cbNode, (<JSDocImplementsTag>node).class);
508            case SyntaxKind.JSDocAugmentsTag:
509                return visitNode(cbNode, (node as JSDocTag).tagName) ||
510                    visitNode(cbNode, (<JSDocAugmentsTag>node).class);
511            case SyntaxKind.JSDocTemplateTag:
512                return visitNode(cbNode, (node as JSDocTag).tagName) ||
513                    visitNode(cbNode, (<JSDocTemplateTag>node).constraint) ||
514                    visitNodes(cbNode, cbNodes, (<JSDocTemplateTag>node).typeParameters);
515            case SyntaxKind.JSDocTypedefTag:
516                return visitNode(cbNode, (node as JSDocTag).tagName) ||
517                    ((node as JSDocTypedefTag).typeExpression &&
518                        (node as JSDocTypedefTag).typeExpression!.kind === SyntaxKind.JSDocTypeExpression
519                        ? visitNode(cbNode, (<JSDocTypedefTag>node).typeExpression) ||
520                            visitNode(cbNode, (<JSDocTypedefTag>node).fullName)
521                        : visitNode(cbNode, (<JSDocTypedefTag>node).fullName) ||
522                            visitNode(cbNode, (<JSDocTypedefTag>node).typeExpression));
523            case SyntaxKind.JSDocCallbackTag:
524                return visitNode(cbNode, (node as JSDocTag).tagName) ||
525                    visitNode(cbNode, (node as JSDocCallbackTag).fullName) ||
526                    visitNode(cbNode, (node as JSDocCallbackTag).typeExpression);
527            case SyntaxKind.JSDocReturnTag:
528            case SyntaxKind.JSDocTypeTag:
529            case SyntaxKind.JSDocThisTag:
530            case SyntaxKind.JSDocEnumTag:
531                return visitNode(cbNode, (node as JSDocTag).tagName) ||
532                    visitNode(cbNode, (node as JSDocReturnTag | JSDocTypeTag | JSDocThisTag | JSDocEnumTag).typeExpression);
533            case SyntaxKind.JSDocSignature:
534                return forEach((<JSDocSignature>node).typeParameters, cbNode) ||
535                    forEach((<JSDocSignature>node).parameters, cbNode) ||
536                    visitNode(cbNode, (<JSDocSignature>node).type);
537            case SyntaxKind.JSDocTypeLiteral:
538                return forEach((node as JSDocTypeLiteral).jsDocPropertyTags, cbNode);
539            case SyntaxKind.JSDocTag:
540            case SyntaxKind.JSDocClassTag:
541            case SyntaxKind.JSDocPublicTag:
542            case SyntaxKind.JSDocPrivateTag:
543            case SyntaxKind.JSDocProtectedTag:
544            case SyntaxKind.JSDocReadonlyTag:
545                return visitNode(cbNode, (node as JSDocTag).tagName);
546            case SyntaxKind.PartiallyEmittedExpression:
547                return visitNode(cbNode, (<PartiallyEmittedExpression>node).expression);
548        }
549    }
550
551    /** @internal */
552    /**
553     * Invokes a callback for each child of the given node. The 'cbNode' callback is invoked for all child nodes
554     * stored in properties. If a 'cbNodes' callback is specified, it is invoked for embedded arrays; additionally,
555     * unlike `forEachChild`, embedded arrays are flattened and the 'cbNode' callback is invoked for each element.
556     *  If a callback returns a truthy value, iteration stops and that value is returned. Otherwise, undefined is returned.
557     *
558     * @param node a given node to visit its children
559     * @param cbNode a callback to be invoked for all child nodes
560     * @param cbNodes a callback to be invoked for embedded array
561     *
562     * @remarks Unlike `forEachChild`, `forEachChildRecursively` handles recursively invoking the traversal on each child node found,
563     * and while doing so, handles traversing the structure without relying on the callstack to encode the tree structure.
564     */
565    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 {
566        const queue: (Node | NodeArray<Node>)[] = gatherPossibleChildren(rootNode);
567        const parents: Node[] = []; // tracks parent references for elements in queue
568        while (parents.length < queue.length) {
569            parents.push(rootNode);
570        }
571        while (queue.length !== 0) {
572            const current = queue.pop()!;
573            const parent = parents.pop()!;
574            if (isArray(current)) {
575                if (cbNodes) {
576                    const res = cbNodes(current, parent);
577                    if (res) {
578                        if (res === "skip") continue;
579                        return res;
580                    }
581                }
582                for (let i = current.length - 1; i >= 0; --i) {
583                    queue.push(current[i]);
584                    parents.push(parent);
585                }
586            }
587            else {
588                const res = cbNode(current, parent);
589                if (res) {
590                    if (res === "skip") continue;
591                    return res;
592                }
593                if (current.kind >= SyntaxKind.FirstNode) {
594                    // add children in reverse order to the queue, so popping gives the first child
595                    for (const child of gatherPossibleChildren(current)) {
596                        queue.push(child);
597                        parents.push(current);
598                    }
599                }
600            }
601        }
602    }
603
604    function gatherPossibleChildren(node: Node) {
605        const children: (Node | NodeArray<Node>)[] = [];
606        forEachChild(node, addWorkItem, addWorkItem); // By using a stack above and `unshift` here, we emulate a depth-first preorder traversal
607        return children;
608
609        function addWorkItem(n: Node | NodeArray<Node>) {
610            children.unshift(n);
611        }
612    }
613
614    let sourceFileCompilerOptions: CompilerOptions;
615
616    export function createSourceFile(fileName: string, sourceText: string, languageVersion: ScriptTarget, setParentNodes = false, scriptKind?: ScriptKind, option?: CompilerOptions): SourceFile {
617        tracing?.push(tracing.Phase.Parse, "createSourceFile", { path: fileName }, /*separateBeginAndEnd*/ true);
618        performance.mark("beforeParse");
619        let result: SourceFile;
620        sourceFileCompilerOptions = option ?? defaultInitCompilerOptions;
621        perfLogger.logStartParseSourceFile(fileName);
622        if (languageVersion === ScriptTarget.JSON) {
623            result = Parser.parseSourceFile(fileName, sourceText, languageVersion, /*syntaxCursor*/ undefined, setParentNodes, ScriptKind.JSON);
624        }
625        else {
626            result = Parser.parseSourceFile(fileName, sourceText, languageVersion, /*syntaxCursor*/ undefined, setParentNodes, scriptKind);
627        }
628        perfLogger.logStopParseSourceFile();
629
630        performance.mark("afterParse");
631        performance.measure("Parse", "beforeParse", "afterParse");
632        tracing?.pop();
633        return result;
634    }
635
636    export function parseIsolatedEntityName(text: string, languageVersion: ScriptTarget): EntityName | undefined {
637        return Parser.parseIsolatedEntityName(text, languageVersion);
638    }
639
640    /**
641     * Parse json text into SyntaxTree and return node and parse errors if any
642     * @param fileName
643     * @param sourceText
644     */
645    export function parseJsonText(fileName: string, sourceText: string): JsonSourceFile {
646        return Parser.parseJsonText(fileName, sourceText);
647    }
648
649    // See also `isExternalOrCommonJsModule` in utilities.ts
650    export function isExternalModule(file: SourceFile): boolean {
651        return file.externalModuleIndicator !== undefined;
652    }
653
654    // Produces a new SourceFile for the 'newText' provided. The 'textChangeRange' parameter
655    // indicates what changed between the 'text' that this SourceFile has and the 'newText'.
656    // The SourceFile will be created with the compiler attempting to reuse as many nodes from
657    // this file as possible.
658    //
659    // Note: this function mutates nodes from this SourceFile. That means any existing nodes
660    // from this SourceFile that are being held onto may change as a result (including
661    // becoming detached from any SourceFile).  It is recommended that this SourceFile not
662    // be used once 'update' is called on it.
663    export function updateSourceFile(sourceFile: SourceFile, newText: string, textChangeRange: TextChangeRange, aggressiveChecks = false, option?: CompilerOptions): SourceFile {
664        sourceFileCompilerOptions = option ?? defaultInitCompilerOptions;
665        const newSourceFile = IncrementalParser.updateSourceFile(sourceFile, newText, textChangeRange, aggressiveChecks);
666        // 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.
667        // We will manually port the flag to the new source file.
668        (newSourceFile as Mutable<SourceFile>).flags |= (sourceFile.flags & NodeFlags.PermanentlySetIncrementalFlags);
669        return newSourceFile;
670    }
671
672    /* @internal */
673    export function parseIsolatedJSDocComment(content: string, start?: number, length?: number) {
674        const result = Parser.JSDocParser.parseIsolatedJSDocComment(content, start, length);
675        if (result && result.jsDoc) {
676            // because the jsDocComment was parsed out of the source file, it might
677            // not be covered by the fixupParentReferences.
678            Parser.fixupParentReferences(result.jsDoc);
679        }
680
681        return result;
682    }
683
684    /* @internal */
685    // Exposed only for testing.
686    export function parseJSDocTypeExpressionForTests(content: string, start?: number, length?: number) {
687        return Parser.JSDocParser.parseJSDocTypeExpressionForTests(content, start, length);
688    }
689
690    // Implement the parser as a singleton module.  We do this for perf reasons because creating
691    // parser instances can actually be expensive enough to impact us on projects with many source
692    // files.
693    namespace Parser {
694        // Share a single scanner across all calls to parse a source file.  This helps speed things
695        // up by avoiding the cost of creating/compiling scanners over and over again.
696        const scanner = createScanner(ScriptTarget.Latest, /*skipTrivia*/ true);
697
698        const disallowInAndDecoratorContext = NodeFlags.DisallowInContext | NodeFlags.DecoratorContext;
699
700        // capture constructors in 'initializeState' to avoid null checks
701        // tslint:disable variable-name
702        let NodeConstructor: new (kind: SyntaxKind, pos: number, end: number) => Node;
703        let TokenConstructor: new (kind: SyntaxKind, pos: number, end: number) => Node;
704        let IdentifierConstructor: new (kind: SyntaxKind, pos: number, end: number) => Node;
705        let PrivateIdentifierConstructor: new (kind: SyntaxKind, pos: number, end: number) => Node;
706        let SourceFileConstructor: new (kind: SyntaxKind, pos: number, end: number) => Node;
707        // tslint:enable variable-name
708
709        function countNode(node: Node) {
710            nodeCount++;
711            return node;
712        }
713
714        // Rather than using `createBaseNodeFactory` here, we establish a `BaseNodeFactory` that closes over the
715        // constructors above, which are reset each time `initializeState` is called.
716        const baseNodeFactory: BaseNodeFactory = {
717            createBaseSourceFileNode: kind => countNode(new SourceFileConstructor(kind, /*pos*/ 0, /*end*/ 0)),
718            createBaseIdentifierNode: kind => countNode(new IdentifierConstructor(kind, /*pos*/ 0, /*end*/ 0)),
719            createBasePrivateIdentifierNode: kind => countNode(new PrivateIdentifierConstructor(kind, /*pos*/ 0, /*end*/ 0)),
720            createBaseTokenNode: kind => countNode(new TokenConstructor(kind, /*pos*/ 0, /*end*/ 0)),
721            createBaseNode: kind => countNode(new NodeConstructor(kind, /*pos*/ 0, /*end*/ 0))
722        };
723
724        const factory = createNodeFactory(NodeFactoryFlags.NoParenthesizerRules | NodeFactoryFlags.NoNodeConverters | NodeFactoryFlags.NoOriginalNode, baseNodeFactory);
725
726        let fileName: string;
727        let sourceFlags: NodeFlags;
728        let sourceText: string;
729        let languageVersion: ScriptTarget;
730        let scriptKind: ScriptKind;
731        let languageVariant: LanguageVariant;
732        let parseDiagnostics: DiagnosticWithDetachedLocation[];
733        let jsDocDiagnostics: DiagnosticWithDetachedLocation[];
734        let syntaxCursor: IncrementalParser.SyntaxCursor | undefined;
735
736        let currentToken: SyntaxKind;
737        let nodeCount: number;
738        let identifiers: ESMap<string, string>;
739        let privateIdentifiers: ESMap<string, string>;
740        let identifierCount: number;
741
742        let parsingContext: ParsingContext;
743
744        let notParenthesizedArrow: Set<number> | undefined;
745
746        // Flags that dictate what parsing context we're in.  For example:
747        // Whether or not we are in strict parsing mode.  All that changes in strict parsing mode is
748        // that some tokens that would be considered identifiers may be considered keywords.
749        //
750        // When adding more parser context flags, consider which is the more common case that the
751        // flag will be in.  This should be the 'false' state for that flag.  The reason for this is
752        // that we don't store data in our nodes unless the value is in the *non-default* state.  So,
753        // for example, more often than code 'allows-in' (or doesn't 'disallow-in').  We opt for
754        // 'disallow-in' set to 'false'.  Otherwise, if we had 'allowsIn' set to 'true', then almost
755        // all nodes would need extra state on them to store this info.
756        //
757        // Note: 'allowIn' and 'allowYield' track 1:1 with the [in] and [yield] concepts in the ES6
758        // grammar specification.
759        //
760        // An important thing about these context concepts.  By default they are effectively inherited
761        // while parsing through every grammar production.  i.e. if you don't change them, then when
762        // you parse a sub-production, it will have the same context values as the parent production.
763        // This is great most of the time.  After all, consider all the 'expression' grammar productions
764        // and how nearly all of them pass along the 'in' and 'yield' context values:
765        //
766        // EqualityExpression[In, Yield] :
767        //      RelationalExpression[?In, ?Yield]
768        //      EqualityExpression[?In, ?Yield] == RelationalExpression[?In, ?Yield]
769        //      EqualityExpression[?In, ?Yield] != RelationalExpression[?In, ?Yield]
770        //      EqualityExpression[?In, ?Yield] === RelationalExpression[?In, ?Yield]
771        //      EqualityExpression[?In, ?Yield] !== RelationalExpression[?In, ?Yield]
772        //
773        // Where you have to be careful is then understanding what the points are in the grammar
774        // where the values are *not* passed along.  For example:
775        //
776        // SingleNameBinding[Yield,GeneratorParameter]
777        //      [+GeneratorParameter]BindingIdentifier[Yield] Initializer[In]opt
778        //      [~GeneratorParameter]BindingIdentifier[?Yield]Initializer[In, ?Yield]opt
779        //
780        // Here this is saying that if the GeneratorParameter context flag is set, that we should
781        // explicitly set the 'yield' context flag to false before calling into the BindingIdentifier
782        // and we should explicitly unset the 'yield' context flag before calling into the Initializer.
783        // production.  Conversely, if the GeneratorParameter context flag is not set, then we
784        // should leave the 'yield' context flag alone.
785        //
786        // Getting this all correct is tricky and requires careful reading of the grammar to
787        // understand when these values should be changed versus when they should be inherited.
788        //
789        // Note: it should not be necessary to save/restore these flags during speculative/lookahead
790        // parsing.  These context flags are naturally stored and restored through normal recursive
791        // descent parsing and unwinding.
792        let contextFlags: NodeFlags;
793
794        let etsFlags: EtsFlags;
795
796        // Indicates whether we are currently parsing top-level statements.
797        let topLevel = true;
798
799        // Whether or not we've had a parse error since creating the last AST node.  If we have
800        // encountered an error, it will be stored on the next AST node we create.  Parse errors
801        // can be broken down into three categories:
802        //
803        // 1) An error that occurred during scanning.  For example, an unterminated literal, or a
804        //    character that was completely not understood.
805        //
806        // 2) A token was expected, but was not present.  This type of error is commonly produced
807        //    by the 'parseExpected' function.
808        //
809        // 3) A token was present that no parsing function was able to consume.  This type of error
810        //    only occurs in the 'abortParsingListOrMoveToNextToken' function when the parser
811        //    decides to skip the token.
812        //
813        // In all of these cases, we want to mark the next node as having had an error before it.
814        // With this mark, we can know in incremental settings if this node can be reused, or if
815        // we have to reparse it.  If we don't keep this information around, we may just reuse the
816        // node.  in that event we would then not produce the same errors as we did before, causing
817        // significant confusion problems.
818        //
819        // Note: it is necessary that this value be saved/restored during speculative/lookahead
820        // parsing.  During lookahead parsing, we will often create a node.  That node will have
821        // this value attached, and then this value will be set back to 'false'.  If we decide to
822        // rewind, we must get back to the same value we had prior to the lookahead.
823        //
824        // Note: any errors at the end of the file that do not precede a regular node, should get
825        // attached to the EOF token.
826        let parseErrorBeforeNextFinishedNode = false;
827
828        let extendEtsComponentDeclaration: { name: string, type: string, instance: string } | undefined;
829
830        let stylesEtsComponentDeclaration: { name: string, type: string, instance: string } | undefined;
831
832        // A map to record file scope '@styles' function name
833        const fileStylesComponents = new Map<string, SyntaxKind>();
834
835        let currentStructName: string | undefined;
836
837        let stateStylesRootNode: string | undefined;
838
839        // A map to record struct scope '@styles' method name
840        const structStylesComponents = new Map<string, { structName: string, kind: SyntaxKind }>();
841
842        export function parseSourceFile(fileName: string, sourceText: string, languageVersion: ScriptTarget, syntaxCursor: IncrementalParser.SyntaxCursor | undefined, setParentNodes = false, scriptKind?: ScriptKind): SourceFile {
843            scriptKind = ensureScriptKind(fileName, scriptKind);
844            if (scriptKind === ScriptKind.JSON) {
845                const result = parseJsonText(fileName, sourceText, languageVersion, syntaxCursor, setParentNodes);
846                convertToObjectWorker(result, result.parseDiagnostics, /*returnValue*/ false, /*knownRootOptions*/ undefined, /*jsonConversionNotifier*/ undefined);
847                result.referencedFiles = emptyArray;
848                result.typeReferenceDirectives = emptyArray;
849                result.libReferenceDirectives = emptyArray;
850                result.amdDependencies = emptyArray;
851                result.hasNoDefaultLib = false;
852                result.pragmas = emptyMap as ReadonlyPragmaMap;
853                return result;
854            }
855
856            initializeState(fileName, sourceText, languageVersion, syntaxCursor, scriptKind);
857
858            const result = parseSourceFileWorker(languageVersion, setParentNodes, scriptKind);
859
860            clearState();
861
862            return result;
863        }
864
865        export function parseIsolatedEntityName(content: string, languageVersion: ScriptTarget): EntityName | undefined {
866            // Choice of `isDeclarationFile` should be arbitrary
867            initializeState("", content, languageVersion, /*syntaxCursor*/ undefined, ScriptKind.JS);
868            // Prime the scanner.
869            nextToken();
870            const entityName = parseEntityName(/*allowReservedWords*/ true);
871            const isInvalid = token() === SyntaxKind.EndOfFileToken && !parseDiagnostics.length;
872            clearState();
873            return isInvalid ? entityName : undefined;
874        }
875
876        export function parseJsonText(fileName: string, sourceText: string, languageVersion: ScriptTarget = ScriptTarget.ES2015, syntaxCursor?: IncrementalParser.SyntaxCursor, setParentNodes = false): JsonSourceFile {
877            initializeState(fileName, sourceText, languageVersion, syntaxCursor, ScriptKind.JSON);
878            sourceFlags = contextFlags;
879
880            // Prime the scanner.
881            nextToken();
882            const pos = getNodePos();
883            let statements, endOfFileToken;
884            if (token() === SyntaxKind.EndOfFileToken) {
885                statements = createNodeArray([], pos, pos);
886                endOfFileToken = parseTokenNode<EndOfFileToken>();
887            }
888            else {
889                let expression;
890                switch (token()) {
891                    case SyntaxKind.OpenBracketToken:
892                        expression = parseArrayLiteralExpression();
893                        break;
894                    case SyntaxKind.TrueKeyword:
895                    case SyntaxKind.FalseKeyword:
896                    case SyntaxKind.NullKeyword:
897                        expression = parseTokenNode<BooleanLiteral | NullLiteral>();
898                        break;
899                    case SyntaxKind.MinusToken:
900                        if (lookAhead(() => nextToken() === SyntaxKind.NumericLiteral && nextToken() !== SyntaxKind.ColonToken)) {
901                            expression = parsePrefixUnaryExpression() as JsonMinusNumericLiteral;
902                        }
903                        else {
904                            expression = parseObjectLiteralExpression();
905                        }
906                        break;
907                    case SyntaxKind.NumericLiteral:
908                    case SyntaxKind.StringLiteral:
909                        if (lookAhead(() => nextToken() !== SyntaxKind.ColonToken)) {
910                            expression = parseLiteralNode() as StringLiteral | NumericLiteral;
911                            break;
912                        }
913                        // falls through
914                    default:
915                        expression = parseObjectLiteralExpression();
916                        break;
917                }
918
919                const statement = factory.createExpressionStatement(expression) as JsonObjectExpressionStatement;
920                finishNode(statement, pos);
921                statements = createNodeArray([statement], pos);
922                endOfFileToken = parseExpectedToken(SyntaxKind.EndOfFileToken, Diagnostics.Unexpected_token);
923            }
924
925            // Set source file so that errors will be reported with this file name
926            const sourceFile = createSourceFile(fileName, ScriptTarget.ES2015, ScriptKind.JSON, /*isDeclaration*/ false, statements, endOfFileToken, sourceFlags);
927
928            if (setParentNodes) {
929                fixupParentReferences(sourceFile);
930            }
931
932            sourceFile.nodeCount = nodeCount;
933            sourceFile.identifierCount = identifierCount;
934            sourceFile.identifiers = identifiers;
935            sourceFile.parseDiagnostics = attachFileToDiagnostics(parseDiagnostics, sourceFile);
936            if (jsDocDiagnostics) {
937                sourceFile.jsDocDiagnostics = attachFileToDiagnostics(jsDocDiagnostics, sourceFile);
938            }
939
940            const result = sourceFile as JsonSourceFile;
941            clearState();
942            return result;
943        }
944
945        function initializeState(_fileName: string, _sourceText: string, _languageVersion: ScriptTarget, _syntaxCursor: IncrementalParser.SyntaxCursor | undefined, _scriptKind: ScriptKind) {
946            NodeConstructor = objectAllocator.getNodeConstructor();
947            TokenConstructor = objectAllocator.getTokenConstructor();
948            IdentifierConstructor = objectAllocator.getIdentifierConstructor();
949            PrivateIdentifierConstructor = objectAllocator.getPrivateIdentifierConstructor();
950            SourceFileConstructor = objectAllocator.getSourceFileConstructor();
951
952            fileName = normalizePath(_fileName);
953            sourceText = _sourceText;
954            languageVersion = _languageVersion;
955            syntaxCursor = _syntaxCursor;
956            scriptKind = _scriptKind;
957            languageVariant = getLanguageVariant(_scriptKind);
958
959            parseDiagnostics = [];
960            parsingContext = 0;
961            identifiers = new Map<string, string>();
962            privateIdentifiers = new Map<string, string>();
963            identifierCount = 0;
964            nodeCount = 0;
965            sourceFlags = 0;
966            topLevel = true;
967
968            switch (scriptKind) {
969                case ScriptKind.JS:
970                case ScriptKind.JSX:
971                    contextFlags = NodeFlags.JavaScriptFile;
972                    break;
973                case ScriptKind.JSON:
974                    contextFlags = NodeFlags.JavaScriptFile | NodeFlags.JsonFile;
975                    break;
976                case ScriptKind.ETS:
977                    contextFlags = NodeFlags.EtsContext;
978                    break;
979                default:
980                    contextFlags = NodeFlags.None;
981                    break;
982            }
983            if (fileName.endsWith(Extension.Ets)) {
984                contextFlags = NodeFlags.EtsContext;
985            }
986            parseErrorBeforeNextFinishedNode = false;
987
988            // Initialize and prime the scanner before parsing the source elements.
989            scanner.setText(sourceText);
990            scanner.setOnError(scanError);
991            scanner.setScriptTarget(languageVersion);
992            scanner.setLanguageVariant(languageVariant);
993        }
994
995        function clearState() {
996            // Clear out the text the scanner is pointing at, so it doesn't keep anything alive unnecessarily.
997            scanner.clearCommentDirectives();
998            scanner.setText("");
999            scanner.setOnError(undefined);
1000
1001            // Clear any data.  We don't want to accidentally hold onto it for too long.
1002            sourceText = undefined!;
1003            languageVersion = undefined!;
1004            syntaxCursor = undefined;
1005            scriptKind = undefined!;
1006            languageVariant = undefined!;
1007            sourceFlags = 0;
1008            parseDiagnostics = undefined!;
1009            jsDocDiagnostics = undefined!;
1010            parsingContext = 0;
1011            identifiers = undefined!;
1012            notParenthesizedArrow = undefined!;
1013            topLevel = true;
1014            extendEtsComponentDeclaration = undefined;
1015            stylesEtsComponentDeclaration = undefined;
1016            stateStylesRootNode = undefined;
1017            fileStylesComponents.clear();
1018            structStylesComponents.clear();
1019        }
1020
1021        function parseSourceFileWorker(languageVersion: ScriptTarget, setParentNodes: boolean, scriptKind: ScriptKind): SourceFile {
1022            const isDeclarationFile = isDeclarationFileName(fileName);
1023            if (isDeclarationFile) {
1024                contextFlags |= NodeFlags.Ambient;
1025            }
1026
1027            sourceFlags = contextFlags;
1028
1029            // Prime the scanner.
1030            nextToken();
1031
1032            const statements = parseList(ParsingContext.SourceElements, parseStatement);
1033            Debug.assert(token() === SyntaxKind.EndOfFileToken);
1034            const endOfFileToken = addJSDocComment(parseTokenNode<EndOfFileToken>());
1035
1036            const sourceFile = createSourceFile(fileName, languageVersion, scriptKind, isDeclarationFile, statements, endOfFileToken, sourceFlags);
1037
1038            // 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
1039            processCommentPragmas(sourceFile as {} as PragmaContext, sourceText);
1040            processPragmasIntoFields(sourceFile as {} as PragmaContext, reportPragmaDiagnostic);
1041
1042            sourceFile.commentDirectives = scanner.getCommentDirectives();
1043            sourceFile.nodeCount = nodeCount;
1044            sourceFile.identifierCount = identifierCount;
1045            sourceFile.identifiers = identifiers;
1046            sourceFile.parseDiagnostics = attachFileToDiagnostics(parseDiagnostics, sourceFile);
1047            if (jsDocDiagnostics) {
1048                sourceFile.jsDocDiagnostics = attachFileToDiagnostics(jsDocDiagnostics, sourceFile);
1049            }
1050
1051            if (setParentNodes) {
1052                fixupParentReferences(sourceFile);
1053            }
1054
1055            return sourceFile;
1056
1057            function reportPragmaDiagnostic(pos: number, end: number, diagnostic: DiagnosticMessage) {
1058                parseDiagnostics.push(createDetachedDiagnostic(fileName, pos, end, diagnostic));
1059            }
1060        }
1061
1062        function withJSDoc<T extends HasJSDoc>(node: T, hasJSDoc: boolean): T {
1063            return hasJSDoc ? addJSDocComment(node) : node;
1064        }
1065
1066        let hasDeprecatedTag = false;
1067        function addJSDocComment<T extends HasJSDoc>(node: T): T {
1068            Debug.assert(!node.jsDoc); // Should only be called once per node
1069            const jsDoc = mapDefined(getJSDocCommentRanges(node, sourceText), comment => JSDocParser.parseJSDocComment(node, comment.pos, comment.end - comment.pos));
1070            if (jsDoc.length) node.jsDoc = jsDoc;
1071            if (hasDeprecatedTag) {
1072                hasDeprecatedTag = false;
1073                (node as Mutable<T>).flags |= NodeFlags.Deprecated;
1074            }
1075            return node;
1076        }
1077
1078        function reparseTopLevelAwait(sourceFile: SourceFile) {
1079            const savedSyntaxCursor = syntaxCursor;
1080            const baseSyntaxCursor = IncrementalParser.createSyntaxCursor(sourceFile);
1081            syntaxCursor = { currentNode };
1082
1083            const statements: Statement[] = [];
1084            const savedParseDiagnostics = parseDiagnostics;
1085
1086            parseDiagnostics = [];
1087
1088            let pos = 0;
1089            let start = findNextStatementWithAwait(sourceFile.statements, 0);
1090            while (start !== -1) {
1091                // append all statements between pos and start
1092                const prevStatement = sourceFile.statements[pos];
1093                const nextStatement = sourceFile.statements[start];
1094                addRange(statements, sourceFile.statements, pos, start);
1095                pos = findNextStatementWithoutAwait(sourceFile.statements, start);
1096
1097                // append all diagnostics associated with the copied range
1098                const diagnosticStart = findIndex(savedParseDiagnostics, diagnostic => diagnostic.start >= prevStatement.pos);
1099                const diagnosticEnd = diagnosticStart >= 0 ? findIndex(savedParseDiagnostics, diagnostic => diagnostic.start >= nextStatement.pos, diagnosticStart) : -1;
1100                if (diagnosticStart >= 0) {
1101                    addRange(parseDiagnostics, savedParseDiagnostics, diagnosticStart, diagnosticEnd >= 0 ? diagnosticEnd : undefined);
1102                }
1103
1104                // reparse all statements between start and pos. We skip existing diagnostics for the same range and allow the parser to generate new ones.
1105                speculationHelper(() => {
1106                    const savedContextFlags = contextFlags;
1107                    contextFlags |= NodeFlags.AwaitContext;
1108                    scanner.setTextPos(nextStatement.pos);
1109                    nextToken();
1110
1111                    while (token() !== SyntaxKind.EndOfFileToken) {
1112                        const startPos = scanner.getStartPos();
1113                        const statement = parseListElement(ParsingContext.SourceElements, parseStatement);
1114                        statements.push(statement);
1115                        if (startPos === scanner.getStartPos()) {
1116                            nextToken();
1117                        }
1118
1119                        if (pos >= 0) {
1120                            const nonAwaitStatement = sourceFile.statements[pos];
1121                            if (statement.end === nonAwaitStatement.pos) {
1122                                // done reparsing this section
1123                                break;
1124                            }
1125                            if (statement.end > nonAwaitStatement.pos) {
1126                                // we ate into the next statement, so we must reparse it.
1127                                pos = findNextStatementWithoutAwait(sourceFile.statements, pos + 1);
1128                            }
1129                        }
1130                    }
1131
1132                    contextFlags = savedContextFlags;
1133                }, SpeculationKind.Reparse);
1134
1135                // find the next statement containing an `await`
1136                start = pos >= 0 ? findNextStatementWithAwait(sourceFile.statements, pos) : -1;
1137            }
1138
1139            // append all statements between pos and the end of the list
1140            if (pos >= 0) {
1141                const prevStatement = sourceFile.statements[pos];
1142                addRange(statements, sourceFile.statements, pos);
1143
1144                // append all diagnostics associated with the copied range
1145                const diagnosticStart = findIndex(savedParseDiagnostics, diagnostic => diagnostic.start >= prevStatement.pos);
1146                if (diagnosticStart >= 0) {
1147                    addRange(parseDiagnostics, savedParseDiagnostics, diagnosticStart);
1148                }
1149            }
1150
1151            syntaxCursor = savedSyntaxCursor;
1152            return factory.updateSourceFile(sourceFile, setTextRange(factory.createNodeArray(statements), sourceFile.statements));
1153
1154            function containsPossibleTopLevelAwait(node: Node) {
1155                return !(node.flags & NodeFlags.AwaitContext)
1156                    && !!(node.transformFlags & TransformFlags.ContainsPossibleTopLevelAwait);
1157            }
1158
1159            function findNextStatementWithAwait(statements: NodeArray<Statement>, start: number) {
1160                for (let i = start; i < statements.length; i++) {
1161                    if (containsPossibleTopLevelAwait(statements[i])) {
1162                        return i;
1163                    }
1164                }
1165                return -1;
1166            }
1167
1168            function findNextStatementWithoutAwait(statements: NodeArray<Statement>, start: number) {
1169                for (let i = start; i < statements.length; i++) {
1170                    if (!containsPossibleTopLevelAwait(statements[i])) {
1171                        return i;
1172                    }
1173                }
1174                return -1;
1175            }
1176
1177            function currentNode(position: number) {
1178                const node = baseSyntaxCursor.currentNode(position);
1179                if (topLevel && node && containsPossibleTopLevelAwait(node)) {
1180                    node.intersectsChange = true;
1181                }
1182                return node;
1183            }
1184
1185        }
1186
1187        export function fixupParentReferences(rootNode: Node) {
1188            // normally parent references are set during binding. However, for clients that only need
1189            // a syntax tree, and no semantic features, then the binding process is an unnecessary
1190            // overhead.  This functions allows us to set all the parents, without all the expense of
1191            // binding.
1192            setParentRecursive(rootNode, /*incremental*/ true);
1193        }
1194
1195        function createSourceFile(fileName: string, languageVersion: ScriptTarget, scriptKind: ScriptKind, isDeclarationFile: boolean, statements: readonly Statement[], endOfFileToken: EndOfFileToken, flags: NodeFlags): SourceFile {
1196            // code from createNode is inlined here so createNode won't have to deal with special case of creating source files
1197            // this is quite rare comparing to other nodes and createNode should be as fast as possible
1198            let sourceFile = factory.createSourceFile(statements, endOfFileToken, flags);
1199            setTextRangePosWidth(sourceFile, 0, sourceText.length);
1200            setExternalModuleIndicator(sourceFile);
1201
1202            // If we parsed this as an external module, it may contain top-level await
1203            if (!isDeclarationFile && isExternalModule(sourceFile) && sourceFile.transformFlags & TransformFlags.ContainsPossibleTopLevelAwait) {
1204                sourceFile = reparseTopLevelAwait(sourceFile);
1205            }
1206
1207            sourceFile.text = sourceText;
1208            sourceFile.bindDiagnostics = [];
1209            sourceFile.bindSuggestionDiagnostics = undefined;
1210            sourceFile.languageVersion = languageVersion;
1211            sourceFile.fileName = fileName;
1212            sourceFile.languageVariant = getLanguageVariant(scriptKind);
1213            sourceFile.isDeclarationFile = isDeclarationFile;
1214            sourceFile.scriptKind = scriptKind;
1215
1216            return sourceFile;
1217        }
1218
1219        function setContextFlag(val: boolean, flag: NodeFlags) {
1220            if (val) {
1221                contextFlags |= flag;
1222            }
1223            else {
1224                contextFlags &= ~flag;
1225            }
1226        }
1227
1228        function setEtsFlag(val: boolean, flag: EtsFlags) {
1229            if (val) {
1230                etsFlags |= flag;
1231            }
1232            else {
1233                etsFlags &= ~flag;
1234            }
1235        }
1236
1237        function setDisallowInContext(val: boolean) {
1238            setContextFlag(val, NodeFlags.DisallowInContext);
1239        }
1240
1241        function setYieldContext(val: boolean) {
1242            setContextFlag(val, NodeFlags.YieldContext);
1243        }
1244
1245        function setDecoratorContext(val: boolean) {
1246            setContextFlag(val, NodeFlags.DecoratorContext);
1247        }
1248
1249        function setAwaitContext(val: boolean) {
1250            setContextFlag(val, NodeFlags.AwaitContext);
1251        }
1252
1253        function setStructContext(val: boolean) {
1254            setEtsFlag(val, EtsFlags.StructContext);
1255        }
1256
1257        function setEtsComponentsContext(val: boolean) {
1258            setEtsFlag(val, EtsFlags.EtsComponentsContext);
1259        }
1260
1261        function setEtsNewExpressionContext(val: boolean) {
1262            setEtsFlag(val, EtsFlags.EtsNewExpressionContext);
1263        }
1264
1265        function setEtsExtendComponentsContext(val: boolean) {
1266            setEtsFlag(val, EtsFlags.EtsExtendComponentsContext);
1267        }
1268
1269        function setEtsStylesComponentsContext(val: boolean) {
1270            setEtsFlag(val, EtsFlags.EtsStylesComponentsContext);
1271        }
1272
1273        function setEtsBuildContext(val: boolean) {
1274            setEtsFlag(val, EtsFlags.EtsBuildContext);
1275        }
1276
1277        function setEtsBuilderContext(val: boolean) {
1278            setEtsFlag(val, EtsFlags.EtsBuilderContext);
1279        }
1280
1281        function setEtsStateStylesContext(val: boolean) {
1282            setEtsFlag(val, EtsFlags.EtsStateStylesContext);
1283        }
1284
1285        function doOutsideOfContext<T>(context: NodeFlags, func: () => T): T {
1286            // contextFlagsToClear will contain only the context flags that are
1287            // currently set that we need to temporarily clear
1288            // We don't just blindly reset to the previous flags to ensure
1289            // that we do not mutate cached flags for the incremental
1290            // parser (ThisNodeHasError, ThisNodeOrAnySubNodesHasError, and
1291            // HasAggregatedChildData).
1292            const contextFlagsToClear = context & contextFlags;
1293            if (contextFlagsToClear) {
1294                // clear the requested context flags
1295                setContextFlag(/*val*/ false, contextFlagsToClear);
1296                const result = func();
1297                // restore the context flags we just cleared
1298                setContextFlag(/*val*/ true, contextFlagsToClear);
1299                return result;
1300            }
1301
1302            // no need to do anything special as we are not in any of the requested contexts
1303            return func();
1304        }
1305
1306        function doInsideOfContext<T>(context: NodeFlags, func: () => T): T {
1307            // contextFlagsToSet will contain only the context flags that
1308            // are not currently set that we need to temporarily enable.
1309            // We don't just blindly reset to the previous flags to ensure
1310            // that we do not mutate cached flags for the incremental
1311            // parser (ThisNodeHasError, ThisNodeOrAnySubNodesHasError, and
1312            // HasAggregatedChildData).
1313            const contextFlagsToSet = context & ~contextFlags;
1314            if (contextFlagsToSet) {
1315                // set the requested context flags
1316                setContextFlag(/*val*/ true, contextFlagsToSet);
1317                const result = func();
1318                // reset the context flags we just set
1319                setContextFlag(/*val*/ false, contextFlagsToSet);
1320                return result;
1321            }
1322
1323            // no need to do anything special as we are already in all of the requested contexts
1324            return func();
1325        }
1326
1327        function allowInAnd<T>(func: () => T): T {
1328            return doOutsideOfContext(NodeFlags.DisallowInContext, func);
1329        }
1330
1331        function disallowInAnd<T>(func: () => T): T {
1332            return doInsideOfContext(NodeFlags.DisallowInContext, func);
1333        }
1334
1335        function doInYieldContext<T>(func: () => T): T {
1336            return doInsideOfContext(NodeFlags.YieldContext, func);
1337        }
1338
1339        function doInDecoratorContext<T>(func: () => T): T {
1340            // setting Ets Extend Components
1341            const extendDecorator = sourceFileCompilerOptions.ets?.extend?.decorator ?? "Extend";
1342            if (token() === SyntaxKind.Identifier && scanner.getTokenText() === extendDecorator) {
1343                setEtsFlag(true, EtsFlags.EtsExtendComponentsContext);
1344            }
1345            // setting Ets Styles Components
1346            const stylesDecorator = sourceFileCompilerOptions.ets?.styles?.decorator ?? "Styles";
1347            if (token() === SyntaxKind.Identifier && scanner.getTokenText() === stylesDecorator) {
1348                setEtsFlag(true, EtsFlags.EtsStylesComponentsContext);
1349            }
1350            return doInsideOfContext(NodeFlags.DecoratorContext, func);
1351        }
1352
1353        function doInAwaitContext<T>(func: () => T): T {
1354            return doInsideOfContext(NodeFlags.AwaitContext, func);
1355        }
1356
1357        function doOutsideOfAwaitContext<T>(func: () => T): T {
1358            return doOutsideOfContext(NodeFlags.AwaitContext, func);
1359        }
1360
1361        function doInYieldAndAwaitContext<T>(func: () => T): T {
1362            return doInsideOfContext(NodeFlags.YieldContext | NodeFlags.AwaitContext, func);
1363        }
1364
1365        function doOutsideOfYieldAndAwaitContext<T>(func: () => T): T {
1366            return doOutsideOfContext(NodeFlags.YieldContext | NodeFlags.AwaitContext, func);
1367        }
1368
1369        function inContext(flags: NodeFlags) {
1370            return (contextFlags & flags) !== 0;
1371        }
1372
1373        function inEtsFlagsContext(flags: EtsFlags) {
1374            return (etsFlags & flags) !== 0;
1375        }
1376
1377        function inYieldContext() {
1378            return inContext(NodeFlags.YieldContext);
1379        }
1380
1381        function inDisallowInContext() {
1382            return inContext(NodeFlags.DisallowInContext);
1383        }
1384
1385        function inDecoratorContext() {
1386            return inContext(NodeFlags.DecoratorContext);
1387        }
1388
1389        function inAwaitContext() {
1390            return inContext(NodeFlags.AwaitContext);
1391        }
1392
1393        function inEtsContext() {
1394            return inContext(NodeFlags.EtsContext);
1395        }
1396
1397        function inStructContext() {
1398            return inEtsContext() && inEtsFlagsContext(EtsFlags.StructContext);
1399        }
1400
1401        function inEtsComponentsContext() {
1402            return inEtsContext() && inEtsFlagsContext(EtsFlags.EtsComponentsContext);
1403        }
1404
1405        function inEtsNewExpressionContext() {
1406            return inEtsContext() && inEtsFlagsContext(EtsFlags.EtsNewExpressionContext);
1407        }
1408
1409        function inEtsExtendComponentsContext() {
1410            return inEtsContext() && inEtsFlagsContext(EtsFlags.EtsExtendComponentsContext);
1411        }
1412
1413        function inEtsStylesComponentsContext() {
1414            return inEtsContext() && inEtsFlagsContext(EtsFlags.EtsStylesComponentsContext);
1415        }
1416
1417        function inBuildContext() {
1418            return inEtsContext() && inStructContext() && inEtsFlagsContext(EtsFlags.EtsBuildContext);
1419        }
1420
1421        function inBuilderContext() {
1422            return inEtsContext() && inEtsFlagsContext(EtsFlags.EtsBuilderContext);
1423        }
1424
1425        function inEtsStateStylesContext() {
1426            return inEtsContext() && inStructContext() && inEtsFlagsContext(EtsFlags.EtsStateStylesContext);
1427        }
1428
1429        function parseErrorAtCurrentToken(message: DiagnosticMessage, arg0?: any): void {
1430            parseErrorAt(scanner.getTokenPos(), scanner.getTextPos(), message, arg0);
1431        }
1432
1433        function parseErrorAtPosition(start: number, length: number, message: DiagnosticMessage, arg0?: any): void {
1434            // Don't report another error if it would just be at the same position as the last error.
1435            const lastError = lastOrUndefined(parseDiagnostics);
1436            if (!lastError || start !== lastError.start) {
1437                parseDiagnostics.push(createDetachedDiagnostic(fileName, start, length, message, arg0));
1438            }
1439
1440            // Mark that we've encountered an error.  We'll set an appropriate bit on the next
1441            // node we finish so that it can't be reused incrementally.
1442            parseErrorBeforeNextFinishedNode = true;
1443        }
1444
1445        function parseErrorAt(start: number, end: number, message: DiagnosticMessage, arg0?: any): void {
1446            parseErrorAtPosition(start, end - start, message, arg0);
1447        }
1448
1449        function parseErrorAtRange(range: TextRange, message: DiagnosticMessage, arg0?: any): void {
1450            parseErrorAt(range.pos, range.end, message, arg0);
1451        }
1452
1453        function scanError(message: DiagnosticMessage, length: number): void {
1454            parseErrorAtPosition(scanner.getTextPos(), length, message);
1455        }
1456
1457        function getNodePos(): number {
1458            return scanner.getStartPos();
1459        }
1460
1461        function hasPrecedingJSDocComment() {
1462            return scanner.hasPrecedingJSDocComment();
1463        }
1464
1465        // Use this function to access the current token instead of reading the currentToken
1466        // variable. Since function results aren't narrowed in control flow analysis, this ensures
1467        // that the type checker doesn't make wrong assumptions about the type of the current
1468        // token (e.g. a call to nextToken() changes the current token but the checker doesn't
1469        // reason about this side effect).  Mainstream VMs inline simple functions like this, so
1470        // there is no performance penalty.
1471        function token(): SyntaxKind {
1472            return currentToken;
1473        }
1474
1475        function nextTokenWithoutCheck() {
1476            return currentToken = scanner.scan();
1477        }
1478
1479        function nextTokenAnd<T>(func: () => T): T {
1480            nextToken();
1481            return func();
1482        }
1483
1484        function nextToken(): SyntaxKind {
1485            // if the keyword had an escape
1486            if (isKeyword(currentToken) && (scanner.hasUnicodeEscape() || scanner.hasExtendedUnicodeEscape())) {
1487                // issue a parse error for the escape
1488                parseErrorAt(scanner.getTokenPos(), scanner.getTextPos(), Diagnostics.Keywords_cannot_contain_escape_characters);
1489            }
1490            return nextTokenWithoutCheck();
1491        }
1492
1493        function nextTokenJSDoc(): JSDocSyntaxKind {
1494            return currentToken = scanner.scanJsDocToken();
1495        }
1496
1497        function reScanGreaterToken(): SyntaxKind {
1498            return currentToken = scanner.reScanGreaterToken();
1499        }
1500
1501        function reScanSlashToken(): SyntaxKind {
1502            return currentToken = scanner.reScanSlashToken();
1503        }
1504
1505        function reScanTemplateToken(isTaggedTemplate: boolean): SyntaxKind {
1506            return currentToken = scanner.reScanTemplateToken(isTaggedTemplate);
1507        }
1508
1509        function reScanTemplateHeadOrNoSubstitutionTemplate(): SyntaxKind {
1510            return currentToken = scanner.reScanTemplateHeadOrNoSubstitutionTemplate();
1511        }
1512
1513        function reScanLessThanToken(): SyntaxKind {
1514            return currentToken = scanner.reScanLessThanToken();
1515        }
1516
1517        function scanJsxIdentifier(): SyntaxKind {
1518            return currentToken = scanner.scanJsxIdentifier();
1519        }
1520
1521        function scanJsxText(): SyntaxKind {
1522            return currentToken = scanner.scanJsxToken();
1523        }
1524
1525        function scanJsxAttributeValue(): SyntaxKind {
1526            return currentToken = scanner.scanJsxAttributeValue();
1527        }
1528
1529        function speculationHelper<T>(callback: () => T, speculationKind: SpeculationKind): T {
1530            // Keep track of the state we'll need to rollback to if lookahead fails (or if the
1531            // caller asked us to always reset our state).
1532            const saveToken = currentToken;
1533            const saveParseDiagnosticsLength = parseDiagnostics.length;
1534            const saveParseErrorBeforeNextFinishedNode = parseErrorBeforeNextFinishedNode;
1535
1536            // Note: it is not actually necessary to save/restore the context flags here.  That's
1537            // because the saving/restoring of these flags happens naturally through the recursive
1538            // descent nature of our parser.  However, we still store this here just so we can
1539            // assert that invariant holds.
1540            const saveContextFlags = contextFlags;
1541
1542            // If we're only looking ahead, then tell the scanner to only lookahead as well.
1543            // Otherwise, if we're actually speculatively parsing, then tell the scanner to do the
1544            // same.
1545            const result = speculationKind !== SpeculationKind.TryParse
1546                ? scanner.lookAhead(callback)
1547                : scanner.tryScan(callback);
1548
1549            Debug.assert(saveContextFlags === contextFlags);
1550
1551            // If our callback returned something 'falsy' or we're just looking ahead,
1552            // then unconditionally restore us to where we were.
1553            if (!result || speculationKind !== SpeculationKind.TryParse) {
1554                currentToken = saveToken;
1555                if (speculationKind !== SpeculationKind.Reparse) {
1556                    parseDiagnostics.length = saveParseDiagnosticsLength;
1557                }
1558                parseErrorBeforeNextFinishedNode = saveParseErrorBeforeNextFinishedNode;
1559            }
1560
1561            return result;
1562        }
1563
1564        /** Invokes the provided callback then unconditionally restores the parser to the state it
1565         * was in immediately prior to invoking the callback.  The result of invoking the callback
1566         * is returned from this function.
1567         */
1568        function lookAhead<T>(callback: () => T): T {
1569            return speculationHelper(callback, SpeculationKind.Lookahead);
1570        }
1571
1572        /** Invokes the provided callback.  If the callback returns something falsy, then it restores
1573         * the parser to the state it was in immediately prior to invoking the callback.  If the
1574         * callback returns something truthy, then the parser state is not rolled back.  The result
1575         * of invoking the callback is returned from this function.
1576         */
1577        function tryParse<T>(callback: () => T): T {
1578            return speculationHelper(callback, SpeculationKind.TryParse);
1579        }
1580
1581        function isBindingIdentifier(): boolean {
1582            if (token() === SyntaxKind.Identifier) {
1583                return true;
1584            }
1585            return token() > SyntaxKind.LastReservedWord;
1586        }
1587
1588        // Ignore strict mode flag because we will report an error in type checker instead.
1589        function isIdentifier(): boolean {
1590            if (token() === SyntaxKind.Identifier) {
1591                return true;
1592            }
1593
1594            // If we have a 'yield' keyword, and we're in the [yield] context, then 'yield' is
1595            // considered a keyword and is not an identifier.
1596            if (token() === SyntaxKind.YieldKeyword && inYieldContext()) {
1597                return false;
1598            }
1599
1600            // If we have a 'await' keyword, and we're in the [Await] context, then 'await' is
1601            // considered a keyword and is not an identifier.
1602            if (token() === SyntaxKind.AwaitKeyword && inAwaitContext()) {
1603                return false;
1604            }
1605
1606            return token() > SyntaxKind.LastReservedWord;
1607        }
1608
1609        function parseExpected(kind: SyntaxKind, diagnosticMessage?: DiagnosticMessage, shouldAdvance = true): boolean {
1610            if (token() === kind) {
1611                if (shouldAdvance) {
1612                    nextToken();
1613                }
1614                return true;
1615            }
1616
1617            if (token() !== kind && stateStylesRootNode && inEtsStateStylesContext()) {
1618                return true;
1619            }
1620
1621            // Report specific message if provided with one.  Otherwise, report generic fallback message.
1622            if (diagnosticMessage) {
1623                parseErrorAtCurrentToken(diagnosticMessage);
1624            }
1625            else {
1626                parseErrorAtCurrentToken(Diagnostics._0_expected, tokenToString(kind));
1627            }
1628            return false;
1629        }
1630
1631        function parseExpectedJSDoc(kind: JSDocSyntaxKind) {
1632            if (token() === kind) {
1633                nextTokenJSDoc();
1634                return true;
1635            }
1636            parseErrorAtCurrentToken(Diagnostics._0_expected, tokenToString(kind));
1637            return false;
1638        }
1639
1640        function parseOptional(t: SyntaxKind): boolean {
1641            if (token() === t) {
1642                nextToken();
1643                return true;
1644            }
1645            return false;
1646        }
1647
1648        function parseOptionalToken<TKind extends SyntaxKind>(t: TKind): Token<TKind>;
1649        function parseOptionalToken(t: SyntaxKind): Node | undefined {
1650            if (token() === t) {
1651                return parseTokenNode();
1652            }
1653            return undefined;
1654        }
1655
1656        function parseOptionalTokenJSDoc<TKind extends JSDocSyntaxKind>(t: TKind): Token<TKind>;
1657        function parseOptionalTokenJSDoc(t: JSDocSyntaxKind): Node | undefined {
1658            if (token() === t) {
1659                return parseTokenNodeJSDoc();
1660            }
1661            return undefined;
1662        }
1663
1664        function parseExpectedToken<TKind extends SyntaxKind>(t: TKind, diagnosticMessage?: DiagnosticMessage, arg0?: any): Token<TKind>;
1665        function parseExpectedToken(t: SyntaxKind, diagnosticMessage?: DiagnosticMessage, arg0?: any): Node {
1666            return parseOptionalToken(t) ||
1667                createMissingNode(t, /*reportAtCurrentPosition*/ false, diagnosticMessage || Diagnostics._0_expected, arg0 || tokenToString(t));
1668        }
1669
1670        function parseExpectedTokenJSDoc<TKind extends JSDocSyntaxKind>(t: TKind): Token<TKind>;
1671        function parseExpectedTokenJSDoc(t: JSDocSyntaxKind): Node {
1672            return parseOptionalTokenJSDoc(t) ||
1673                createMissingNode(t, /*reportAtCurrentPosition*/ false, Diagnostics._0_expected, tokenToString(t));
1674        }
1675
1676        function parseTokenNode<T extends Node>(): T {
1677            const pos = getNodePos();
1678            const kind = token();
1679            nextToken();
1680            return <T>finishNode(factory.createToken(kind), pos);
1681        }
1682
1683        function parseTokenNodeJSDoc<T extends Node>(): T {
1684            const pos = getNodePos();
1685            const kind = token();
1686            nextTokenJSDoc();
1687            return <T>finishNode(factory.createToken(kind), pos);
1688        }
1689
1690        function canParseSemicolon() {
1691            // If there's a real semicolon, then we can always parse it out.
1692            if (token() === SyntaxKind.SemicolonToken) {
1693                return true;
1694            }
1695
1696            // We can parse out an optional semicolon in ASI cases in the following cases.
1697            return token() === SyntaxKind.CloseBraceToken || token() === SyntaxKind.EndOfFileToken || scanner.hasPrecedingLineBreak();
1698        }
1699
1700        function parseSemicolon(): boolean {
1701            if (canParseSemicolon()) {
1702                if (token() === SyntaxKind.SemicolonToken) {
1703                    // consume the semicolon if it was explicitly provided.
1704                    nextToken();
1705                }
1706
1707                return true;
1708            }
1709            else {
1710                return parseExpected(SyntaxKind.SemicolonToken);
1711            }
1712        }
1713
1714        function createNodeArray<T extends Node>(elements: T[], pos: number, end?: number, hasTrailingComma?: boolean): NodeArray<T> {
1715            const array = factory.createNodeArray(elements, hasTrailingComma);
1716            setTextRangePosEnd(array, pos, end ?? scanner.getStartPos());
1717            return array;
1718        }
1719
1720        function finishNode<T extends Node>(node: T, pos: number, end?: number, virtual?: boolean): T {
1721            setTextRangePosEnd(node, pos, end ?? scanner.getStartPos());
1722            if (contextFlags) {
1723                (node as Mutable<T>).flags |= contextFlags;
1724            }
1725
1726            // Keep track on the node if we encountered an error while parsing it.  If we did, then
1727            // we cannot reuse the node incrementally.  Once we've marked this node, clear out the
1728            // flag so that we don't mark any subsequent nodes.
1729            if (parseErrorBeforeNextFinishedNode) {
1730                parseErrorBeforeNextFinishedNode = false;
1731                (node as Mutable<T>).flags |= NodeFlags.ThisNodeHasError;
1732            }
1733
1734            if (virtual) {
1735                node.virtual = true;
1736            }
1737
1738            return node;
1739        }
1740
1741        function createMissingNode<T extends Node>(kind: T["kind"], reportAtCurrentPosition: false, diagnosticMessage?: DiagnosticMessage, arg0?: any): T;
1742        function createMissingNode<T extends Node>(kind: T["kind"], reportAtCurrentPosition: boolean, diagnosticMessage: DiagnosticMessage, arg0?: any): T;
1743        function createMissingNode<T extends Node>(kind: T["kind"], reportAtCurrentPosition: boolean, diagnosticMessage: DiagnosticMessage, arg0?: any): T {
1744            if (reportAtCurrentPosition) {
1745                parseErrorAtPosition(scanner.getStartPos(), 0, diagnosticMessage, arg0);
1746            }
1747            else if (diagnosticMessage) {
1748                parseErrorAtCurrentToken(diagnosticMessage, arg0);
1749            }
1750
1751            const pos = getNodePos();
1752            const result =
1753                kind === SyntaxKind.Identifier ? factory.createIdentifier("", /*typeArguments*/ undefined, /*originalKeywordKind*/ undefined) :
1754                isTemplateLiteralKind(kind) ? factory.createTemplateLiteralLikeNode(kind, "", "", /*templateFlags*/ undefined) :
1755                kind === SyntaxKind.NumericLiteral ? factory.createNumericLiteral("", /*numericLiteralFlags*/ undefined) :
1756                kind === SyntaxKind.StringLiteral ? factory.createStringLiteral("", /*isSingleQuote*/ undefined) :
1757                kind === SyntaxKind.MissingDeclaration ? factory.createMissingDeclaration() :
1758                factory.createToken(kind);
1759            return finishNode(result, pos) as T;
1760        }
1761
1762        function internIdentifier(text: string): string {
1763            let identifier = identifiers.get(text);
1764            if (identifier === undefined) {
1765                identifiers.set(text, identifier = text);
1766            }
1767            return identifier;
1768        }
1769
1770        // An identifier that starts with two underscores has an extra underscore character prepended to it to avoid issues
1771        // with magic property names like '__proto__'. The 'identifiers' object is used to share a single string instance for
1772        // each identifier in order to reduce memory consumption.
1773        function createIdentifier(isIdentifier: boolean, diagnosticMessage?: DiagnosticMessage, privateIdentifierDiagnosticMessage?: DiagnosticMessage): Identifier {
1774            if (isIdentifier) {
1775                identifierCount++;
1776                const pos = getNodePos();
1777                // Store original token kind if it is not just an Identifier so we can report appropriate error later in type checker
1778                const originalKeywordKind = token();
1779                const text = internIdentifier(scanner.getTokenValue());
1780                nextTokenWithoutCheck();
1781                return finishNode(factory.createIdentifier(text, /*typeArguments*/ undefined, originalKeywordKind), pos);
1782            }
1783
1784            if (token() === SyntaxKind.PrivateIdentifier) {
1785                parseErrorAtCurrentToken(privateIdentifierDiagnosticMessage || Diagnostics.Private_identifiers_are_not_allowed_outside_class_bodies);
1786                return createIdentifier(/*isIdentifier*/ true);
1787            }
1788
1789            if (token() === SyntaxKind.Unknown && scanner.tryScan(() => scanner.reScanInvalidIdentifier() === SyntaxKind.Identifier)) {
1790                // Scanner has already recorded an 'Invalid character' error, so no need to add another from the parser.
1791                return createIdentifier(/*isIdentifier*/ true);
1792            }
1793
1794            if (stateStylesRootNode && inEtsStateStylesContext() && token() === SyntaxKind.DotToken) {
1795                identifierCount++;
1796                const pos = getNodePos();
1797                return finishVirtualNode(
1798                    factory.createIdentifier(`${stateStylesRootNode}Instance`, /*typeArguments*/ undefined, SyntaxKind.Identifier),
1799                    pos,
1800                    pos
1801                );
1802            }
1803
1804            identifierCount++;
1805            // Only for end of file because the error gets reported incorrectly on embedded script tags.
1806            const reportAtCurrentPosition = token() === SyntaxKind.EndOfFileToken;
1807
1808            const isReservedWord = scanner.isReservedWord();
1809            const msgArg = scanner.getTokenText();
1810
1811            const defaultMessage = isReservedWord ?
1812                Diagnostics.Identifier_expected_0_is_a_reserved_word_that_cannot_be_used_here :
1813                Diagnostics.Identifier_expected;
1814
1815            return createMissingNode<Identifier>(SyntaxKind.Identifier, reportAtCurrentPosition, diagnosticMessage || defaultMessage, msgArg);
1816        }
1817
1818        function parseBindingIdentifier(privateIdentifierDiagnosticMessage?: DiagnosticMessage) {
1819            return createIdentifier(isBindingIdentifier(), /*diagnosticMessage*/ undefined, privateIdentifierDiagnosticMessage);
1820        }
1821
1822        function parseIdentifier(diagnosticMessage?: DiagnosticMessage, privateIdentifierDiagnosticMessage?: DiagnosticMessage): Identifier {
1823            return createIdentifier(isIdentifier(), diagnosticMessage, privateIdentifierDiagnosticMessage);
1824        }
1825
1826        function parseEtsIdentifier(pos: number): Identifier {
1827            identifierCount++;
1828            const text = internIdentifier(stylesEtsComponentDeclaration!.type);
1829            return finishVirtualNode(factory.createIdentifier(text), pos, pos);
1830        }
1831
1832        function parseIdentifierName(diagnosticMessage?: DiagnosticMessage): Identifier {
1833            return createIdentifier(tokenIsIdentifierOrKeyword(token()), diagnosticMessage);
1834        }
1835
1836        function isLiteralPropertyName(): boolean {
1837            return tokenIsIdentifierOrKeyword(token()) ||
1838                token() === SyntaxKind.StringLiteral ||
1839                token() === SyntaxKind.NumericLiteral;
1840        }
1841
1842        function parsePropertyNameWorker(allowComputedPropertyNames: boolean): PropertyName {
1843            if (token() === SyntaxKind.StringLiteral || token() === SyntaxKind.NumericLiteral) {
1844                const node = <StringLiteral | NumericLiteral>parseLiteralNode();
1845                node.text = internIdentifier(node.text);
1846                return node;
1847            }
1848            if (allowComputedPropertyNames && token() === SyntaxKind.OpenBracketToken) {
1849                return parseComputedPropertyName();
1850            }
1851            if (token() === SyntaxKind.PrivateIdentifier) {
1852                return parsePrivateIdentifier();
1853            }
1854            return parseIdentifierName();
1855        }
1856
1857        function parsePropertyName(): PropertyName {
1858            return parsePropertyNameWorker(/*allowComputedPropertyNames*/ true);
1859        }
1860
1861        function parseComputedPropertyName(): ComputedPropertyName {
1862            // PropertyName [Yield]:
1863            //      LiteralPropertyName
1864            //      ComputedPropertyName[?Yield]
1865            const pos = getNodePos();
1866            parseExpected(SyntaxKind.OpenBracketToken);
1867            // We parse any expression (including a comma expression). But the grammar
1868            // says that only an assignment expression is allowed, so the grammar checker
1869            // will error if it sees a comma expression.
1870            const expression = allowInAnd(parseExpression);
1871            parseExpected(SyntaxKind.CloseBracketToken);
1872            return finishNode(factory.createComputedPropertyName(expression), pos);
1873        }
1874
1875        function internPrivateIdentifier(text: string): string {
1876            let privateIdentifier = privateIdentifiers.get(text);
1877            if (privateIdentifier === undefined) {
1878                privateIdentifiers.set(text, privateIdentifier = text);
1879            }
1880            return privateIdentifier;
1881        }
1882
1883        function parsePrivateIdentifier(): PrivateIdentifier {
1884            const pos = getNodePos();
1885            const node = factory.createPrivateIdentifier(internPrivateIdentifier(scanner.getTokenText()));
1886            nextToken();
1887            return finishNode(node, pos);
1888        }
1889
1890        function parseContextualModifier(t: SyntaxKind): boolean {
1891            return token() === t && tryParse(nextTokenCanFollowModifier);
1892        }
1893
1894        function nextTokenIsOnSameLineAndCanFollowModifier() {
1895            nextToken();
1896            if (scanner.hasPrecedingLineBreak()) {
1897                return false;
1898            }
1899            return canFollowModifier();
1900        }
1901
1902        function nextTokenCanFollowModifier() {
1903            switch (token()) {
1904                case SyntaxKind.ConstKeyword:
1905                    // 'const' is only a modifier if followed by 'enum'.
1906                    return nextToken() === SyntaxKind.EnumKeyword;
1907                case SyntaxKind.ExportKeyword:
1908                    nextToken();
1909                    if (token() === SyntaxKind.DefaultKeyword) {
1910                        return lookAhead(nextTokenCanFollowDefaultKeyword);
1911                    }
1912                    if (token() === SyntaxKind.TypeKeyword) {
1913                        return lookAhead(nextTokenCanFollowExportModifier);
1914                    }
1915                    return canFollowExportModifier();
1916                case SyntaxKind.DefaultKeyword:
1917                    return nextTokenCanFollowDefaultKeyword();
1918                case SyntaxKind.StaticKeyword:
1919                    return nextTokenIsOnSameLineAndCanFollowModifier();
1920                case SyntaxKind.GetKeyword:
1921                case SyntaxKind.SetKeyword:
1922                    nextToken();
1923                    return canFollowModifier();
1924                default:
1925                    return nextTokenIsOnSameLineAndCanFollowModifier();
1926            }
1927        }
1928
1929        function canFollowExportModifier(): boolean {
1930            return token() !== SyntaxKind.AsteriskToken
1931                && token() !== SyntaxKind.AsKeyword
1932                && token() !== SyntaxKind.OpenBraceToken
1933                && canFollowModifier();
1934        }
1935
1936        function nextTokenCanFollowExportModifier(): boolean {
1937            nextToken();
1938            return canFollowExportModifier();
1939        }
1940
1941        function parseAnyContextualModifier(): boolean {
1942            return isModifierKind(token()) && tryParse(nextTokenCanFollowModifier);
1943        }
1944
1945        function canFollowModifier(): boolean {
1946            return token() === SyntaxKind.OpenBracketToken
1947                || token() === SyntaxKind.OpenBraceToken
1948                || token() === SyntaxKind.AsteriskToken
1949                || token() === SyntaxKind.DotDotDotToken
1950                || isLiteralPropertyName();
1951        }
1952
1953        function nextTokenCanFollowDefaultKeyword(): boolean {
1954            nextToken();
1955            return token() === SyntaxKind.ClassKeyword || (inEtsContext() && token() === SyntaxKind.StructKeyword) ||
1956                token() === SyntaxKind.FunctionKeyword || token() === SyntaxKind.InterfaceKeyword ||
1957                (token() === SyntaxKind.AbstractKeyword && lookAhead(nextTokenIsClassKeywordOnSameLine)) ||
1958                (token() === SyntaxKind.AsyncKeyword && lookAhead(nextTokenIsFunctionKeywordOnSameLine));
1959        }
1960
1961        // True if positioned at the start of a list element
1962        function isListElement(parsingContext: ParsingContext, inErrorRecovery: boolean): boolean {
1963            const node = currentNode(parsingContext);
1964            if (node) {
1965                return true;
1966            }
1967
1968            switch (parsingContext) {
1969                case ParsingContext.SourceElements:
1970                case ParsingContext.BlockStatements:
1971                case ParsingContext.SwitchClauseStatements:
1972                    // If we're in error recovery, then we don't want to treat ';' as an empty statement.
1973                    // The problem is that ';' can show up in far too many contexts, and if we see one
1974                    // and assume it's a statement, then we may bail out inappropriately from whatever
1975                    // we're parsing.  For example, if we have a semicolon in the middle of a class, then
1976                    // we really don't want to assume the class is over and we're on a statement in the
1977                    // outer module.  We just want to consume and move on.
1978                    return !(token() === SyntaxKind.SemicolonToken && inErrorRecovery) && isStartOfStatement();
1979                case ParsingContext.SwitchClauses:
1980                    return token() === SyntaxKind.CaseKeyword || token() === SyntaxKind.DefaultKeyword;
1981                case ParsingContext.TypeMembers:
1982                    return lookAhead(isTypeMemberStart);
1983                case ParsingContext.ClassMembers:
1984                    // We allow semicolons as class elements (as specified by ES6) as long as we're
1985                    // not in error recovery.  If we're in error recovery, we don't want an errant
1986                    // semicolon to be treated as a class member (since they're almost always used
1987                    // for statements.
1988                    return lookAhead(isClassMemberStart) || (token() === SyntaxKind.SemicolonToken && !inErrorRecovery);
1989                case ParsingContext.EnumMembers:
1990                    // Include open bracket computed properties. This technically also lets in indexers,
1991                    // which would be a candidate for improved error reporting.
1992                    return token() === SyntaxKind.OpenBracketToken || isLiteralPropertyName();
1993                case ParsingContext.ObjectLiteralMembers:
1994                    switch (token()) {
1995                        case SyntaxKind.OpenBracketToken:
1996                        case SyntaxKind.AsteriskToken:
1997                        case SyntaxKind.DotDotDotToken:
1998                        case SyntaxKind.DotToken: // Not an object literal member, but don't want to close the object (see `tests/cases/fourslash/completionsDotInObjectLiteral.ts`)
1999                            return true;
2000                        default:
2001                            return isLiteralPropertyName();
2002                    }
2003                case ParsingContext.RestProperties:
2004                    return isLiteralPropertyName();
2005                case ParsingContext.ObjectBindingElements:
2006                    return token() === SyntaxKind.OpenBracketToken || token() === SyntaxKind.DotDotDotToken || isLiteralPropertyName();
2007                case ParsingContext.HeritageClauseElement:
2008                    // If we see `{ ... }` then only consume it as an expression if it is followed by `,` or `{`
2009                    // That way we won't consume the body of a class in its heritage clause.
2010                    if (token() === SyntaxKind.OpenBraceToken) {
2011                        return lookAhead(isValidHeritageClauseObjectLiteral);
2012                    }
2013
2014                    if (!inErrorRecovery) {
2015                        return isStartOfLeftHandSideExpression() && !isHeritageClauseExtendsOrImplementsKeyword();
2016                    }
2017                    else {
2018                        // If we're in error recovery we tighten up what we're willing to match.
2019                        // That way we don't treat something like "this" as a valid heritage clause
2020                        // element during recovery.
2021                        return isIdentifier() && !isHeritageClauseExtendsOrImplementsKeyword();
2022                    }
2023                case ParsingContext.VariableDeclarations:
2024                    return isBindingIdentifierOrPrivateIdentifierOrPattern();
2025                case ParsingContext.ArrayBindingElements:
2026                    return token() === SyntaxKind.CommaToken || token() === SyntaxKind.DotDotDotToken || isBindingIdentifierOrPrivateIdentifierOrPattern();
2027                case ParsingContext.TypeParameters:
2028                    return isIdentifier() || isValidStylesContext();
2029                case ParsingContext.ArrayLiteralMembers:
2030                    switch (token()) {
2031                        case SyntaxKind.CommaToken:
2032                        case SyntaxKind.DotToken: // Not an array literal member, but don't want to close the array (see `tests/cases/fourslash/completionsDotInArrayLiteralInObjectLiteral.ts`)
2033                            return true;
2034                    }
2035                    // falls through
2036                case ParsingContext.ArgumentExpressions:
2037                    return token() === SyntaxKind.DotDotDotToken || isStartOfExpression();
2038                case ParsingContext.Parameters:
2039                    return isStartOfParameter(/*isJSDocParameter*/ false);
2040                case ParsingContext.JSDocParameters:
2041                    return isStartOfParameter(/*isJSDocParameter*/ true);
2042                case ParsingContext.TypeArguments:
2043                case ParsingContext.TupleElementTypes:
2044                    return token() === SyntaxKind.CommaToken || isStartOfType();
2045                case ParsingContext.HeritageClauses:
2046                    return isHeritageClause();
2047                case ParsingContext.ImportOrExportSpecifiers:
2048                    return tokenIsIdentifierOrKeyword(token());
2049                case ParsingContext.JsxAttributes:
2050                    return tokenIsIdentifierOrKeyword(token()) || token() === SyntaxKind.OpenBraceToken;
2051                case ParsingContext.JsxChildren:
2052                    return true;
2053            }
2054
2055            return Debug.fail("Non-exhaustive case in 'isListElement'.");
2056        }
2057
2058        function isValidStylesContext(): boolean {
2059            return (inEtsStylesComponentsContext() && stylesEtsComponentDeclaration !== undefined);
2060        }
2061
2062        function isValidHeritageClauseObjectLiteral() {
2063            Debug.assert(token() === SyntaxKind.OpenBraceToken);
2064            if (nextToken() === SyntaxKind.CloseBraceToken) {
2065                // if we see "extends {}" then only treat the {} as what we're extending (and not
2066                // the class body) if we have:
2067                //
2068                //      extends {} {
2069                //      extends {},
2070                //      extends {} extends
2071                //      extends {} implements
2072
2073                const next = nextToken();
2074                return next === SyntaxKind.CommaToken || next === SyntaxKind.OpenBraceToken || next === SyntaxKind.ExtendsKeyword || next === SyntaxKind.ImplementsKeyword;
2075            }
2076
2077            return true;
2078        }
2079
2080        function nextTokenIsIdentifier() {
2081            nextToken();
2082            return isIdentifier();
2083        }
2084
2085        function nextTokenIsIdentifierOrKeyword() {
2086            nextToken();
2087            return tokenIsIdentifierOrKeyword(token());
2088        }
2089
2090        function nextTokenIsIdentifierOrKeywordOrGreaterThan() {
2091            nextToken();
2092            return tokenIsIdentifierOrKeywordOrGreaterThan(token());
2093        }
2094
2095        function isHeritageClauseExtendsOrImplementsKeyword(): boolean {
2096            if (token() === SyntaxKind.ImplementsKeyword ||
2097                token() === SyntaxKind.ExtendsKeyword) {
2098
2099                return lookAhead(nextTokenIsStartOfExpression);
2100            }
2101
2102            return false;
2103        }
2104
2105        function nextTokenIsStartOfExpression() {
2106            nextToken();
2107            return isStartOfExpression();
2108        }
2109
2110        function nextTokenIsStartOfType() {
2111            nextToken();
2112            return isStartOfType();
2113        }
2114
2115        // True if positioned at a list terminator
2116        function isListTerminator(kind: ParsingContext): boolean {
2117            if (token() === SyntaxKind.EndOfFileToken) {
2118                // Being at the end of the file ends all lists.
2119                return true;
2120            }
2121
2122            switch (kind) {
2123                case ParsingContext.BlockStatements:
2124                case ParsingContext.SwitchClauses:
2125                case ParsingContext.TypeMembers:
2126                case ParsingContext.ClassMembers:
2127                case ParsingContext.EnumMembers:
2128                case ParsingContext.ObjectLiteralMembers:
2129                case ParsingContext.ObjectBindingElements:
2130                case ParsingContext.ImportOrExportSpecifiers:
2131                    return token() === SyntaxKind.CloseBraceToken;
2132                case ParsingContext.SwitchClauseStatements:
2133                    return token() === SyntaxKind.CloseBraceToken || token() === SyntaxKind.CaseKeyword || token() === SyntaxKind.DefaultKeyword;
2134                case ParsingContext.HeritageClauseElement:
2135                    return token() === SyntaxKind.OpenBraceToken || token() === SyntaxKind.ExtendsKeyword || token() === SyntaxKind.ImplementsKeyword;
2136                case ParsingContext.VariableDeclarations:
2137                    return isVariableDeclaratorListTerminator();
2138                case ParsingContext.TypeParameters:
2139                    // Tokens other than '>' are here for better error recovery
2140                    return token() === SyntaxKind.GreaterThanToken || token() === SyntaxKind.OpenParenToken || token() === SyntaxKind.OpenBraceToken || token() === SyntaxKind.ExtendsKeyword || token() === SyntaxKind.ImplementsKeyword;
2141                case ParsingContext.ArgumentExpressions:
2142                    // Tokens other than ')' are here for better error recovery
2143                    return token() === SyntaxKind.CloseParenToken || token() === SyntaxKind.SemicolonToken;
2144                case ParsingContext.ArrayLiteralMembers:
2145                case ParsingContext.TupleElementTypes:
2146                case ParsingContext.ArrayBindingElements:
2147                    return token() === SyntaxKind.CloseBracketToken;
2148                case ParsingContext.JSDocParameters:
2149                case ParsingContext.Parameters:
2150                case ParsingContext.RestProperties:
2151                    // Tokens other than ')' and ']' (the latter for index signatures) are here for better error recovery
2152                    return token() === SyntaxKind.CloseParenToken || token() === SyntaxKind.CloseBracketToken /*|| token === SyntaxKind.OpenBraceToken*/;
2153                case ParsingContext.TypeArguments:
2154                    // All other tokens should cause the type-argument to terminate except comma token
2155                    return token() !== SyntaxKind.CommaToken;
2156                case ParsingContext.HeritageClauses:
2157                    return token() === SyntaxKind.OpenBraceToken || token() === SyntaxKind.CloseBraceToken;
2158                case ParsingContext.JsxAttributes:
2159                    return token() === SyntaxKind.GreaterThanToken || token() === SyntaxKind.SlashToken;
2160                case ParsingContext.JsxChildren:
2161                    return token() === SyntaxKind.LessThanToken && lookAhead(nextTokenIsSlash);
2162                default:
2163                    return false;
2164            }
2165        }
2166
2167        function isVariableDeclaratorListTerminator(): boolean {
2168            // If we can consume a semicolon (either explicitly, or with ASI), then consider us done
2169            // with parsing the list of variable declarators.
2170            if (canParseSemicolon()) {
2171                return true;
2172            }
2173
2174            // in the case where we're parsing the variable declarator of a 'for-in' statement, we
2175            // are done if we see an 'in' keyword in front of us. Same with for-of
2176            if (isInOrOfKeyword(token())) {
2177                return true;
2178            }
2179
2180            // ERROR RECOVERY TWEAK:
2181            // For better error recovery, if we see an '=>' then we just stop immediately.  We've got an
2182            // arrow function here and it's going to be very unlikely that we'll resynchronize and get
2183            // another variable declaration.
2184            if (token() === SyntaxKind.EqualsGreaterThanToken) {
2185                return true;
2186            }
2187
2188            // Keep trying to parse out variable declarators.
2189            return false;
2190        }
2191
2192        // True if positioned at element or terminator of the current list or any enclosing list
2193        function isInSomeParsingContext(): boolean {
2194            for (let kind = 0; kind < ParsingContext.Count; kind++) {
2195                if (parsingContext & (1 << kind)) {
2196                    if (isListElement(kind, /*inErrorRecovery*/ true) || isListTerminator(kind)) {
2197                        return true;
2198                    }
2199                }
2200            }
2201
2202            return false;
2203        }
2204
2205        // Parses a list of elements
2206        function parseList<T extends Node>(kind: ParsingContext, parseElement: () => T): NodeArray<T> {
2207            const saveParsingContext = parsingContext;
2208            parsingContext |= 1 << kind;
2209            const list = [];
2210            const listPos = getNodePos();
2211
2212            while (!isListTerminator(kind)) {
2213                if (isListElement(kind, /*inErrorRecovery*/ false)) {
2214                    const element = parseListElement(kind, parseElement);
2215                    list.push(element);
2216
2217                    continue;
2218                }
2219
2220                if (abortParsingListOrMoveToNextToken(kind)) {
2221                    break;
2222                }
2223            }
2224
2225            parsingContext = saveParsingContext;
2226            return createNodeArray(list, listPos);
2227        }
2228
2229        function parseListElement<T extends Node>(parsingContext: ParsingContext, parseElement: () => T): T {
2230            const node = currentNode(parsingContext);
2231            if (node) {
2232                return <T>consumeNode(node);
2233            }
2234
2235            return parseElement();
2236        }
2237
2238        function currentNode(parsingContext: ParsingContext): Node | undefined {
2239            // If we don't have a cursor or the parsing context isn't reusable, there's nothing to reuse.
2240            //
2241            // If there is an outstanding parse error that we've encountered, but not attached to
2242            // some node, then we cannot get a node from the old source tree.  This is because we
2243            // want to mark the next node we encounter as being unusable.
2244            //
2245            // Note: This may be too conservative.  Perhaps we could reuse the node and set the bit
2246            // on it (or its leftmost child) as having the error.  For now though, being conservative
2247            // is nice and likely won't ever affect perf.
2248            if (!syntaxCursor || !isReusableParsingContext(parsingContext) || parseErrorBeforeNextFinishedNode) {
2249                return undefined;
2250            }
2251
2252            const node = syntaxCursor.currentNode(scanner.getStartPos());
2253
2254            // Can't reuse a missing node.
2255            // Can't reuse a node that intersected the change range.
2256            // Can't reuse a node that contains a parse error.  This is necessary so that we
2257            // produce the same set of errors again.
2258            if (nodeIsMissing(node) || node.intersectsChange || containsParseError(node)) {
2259                return undefined;
2260            }
2261
2262            // We can only reuse a node if it was parsed under the same strict mode that we're
2263            // currently in.  i.e. if we originally parsed a node in non-strict mode, but then
2264            // the user added 'using strict' at the top of the file, then we can't use that node
2265            // again as the presence of strict mode may cause us to parse the tokens in the file
2266            // differently.
2267            //
2268            // Note: we *can* reuse tokens when the strict mode changes.  That's because tokens
2269            // are unaffected by strict mode.  It's just the parser will decide what to do with it
2270            // differently depending on what mode it is in.
2271            //
2272            // This also applies to all our other context flags as well.
2273            const nodeContextFlags = node.flags & NodeFlags.ContextFlags;
2274            if (nodeContextFlags !== contextFlags) {
2275                return undefined;
2276            }
2277
2278            // Ok, we have a node that looks like it could be reused.  Now verify that it is valid
2279            // in the current list parsing context that we're currently at.
2280            if (!canReuseNode(node, parsingContext)) {
2281                return undefined;
2282            }
2283
2284            if ((node as JSDocContainer).jsDocCache) {
2285                // jsDocCache may include tags from parent nodes, which might have been modified.
2286                (node as JSDocContainer).jsDocCache = undefined;
2287            }
2288
2289            return node;
2290        }
2291
2292        function consumeNode(node: Node) {
2293            // Move the scanner so it is after the node we just consumed.
2294            scanner.setTextPos(node.end);
2295            nextToken();
2296            return node;
2297        }
2298
2299        function isReusableParsingContext(parsingContext: ParsingContext): boolean {
2300            switch (parsingContext) {
2301                case ParsingContext.ClassMembers:
2302                case ParsingContext.SwitchClauses:
2303                case ParsingContext.SourceElements:
2304                case ParsingContext.BlockStatements:
2305                case ParsingContext.SwitchClauseStatements:
2306                case ParsingContext.EnumMembers:
2307                case ParsingContext.TypeMembers:
2308                case ParsingContext.VariableDeclarations:
2309                case ParsingContext.JSDocParameters:
2310                case ParsingContext.Parameters:
2311                    return true;
2312            }
2313            return false;
2314        }
2315
2316        function canReuseNode(node: Node, parsingContext: ParsingContext): boolean {
2317            switch (parsingContext) {
2318                case ParsingContext.ClassMembers:
2319                    return isReusableClassMember(node);
2320
2321                case ParsingContext.SwitchClauses:
2322                    return isReusableSwitchClause(node);
2323
2324                case ParsingContext.SourceElements:
2325                case ParsingContext.BlockStatements:
2326                case ParsingContext.SwitchClauseStatements:
2327                    return isReusableStatement(node);
2328
2329                case ParsingContext.EnumMembers:
2330                    return isReusableEnumMember(node);
2331
2332                case ParsingContext.TypeMembers:
2333                    return isReusableTypeMember(node);
2334
2335                case ParsingContext.VariableDeclarations:
2336                    return isReusableVariableDeclaration(node);
2337
2338                case ParsingContext.JSDocParameters:
2339                case ParsingContext.Parameters:
2340                    return isReusableParameter(node);
2341
2342                // Any other lists we do not care about reusing nodes in.  But feel free to add if
2343                // you can do so safely.  Danger areas involve nodes that may involve speculative
2344                // parsing.  If speculative parsing is involved with the node, then the range the
2345                // parser reached while looking ahead might be in the edited range (see the example
2346                // in canReuseVariableDeclaratorNode for a good case of this).
2347
2348                // case ParsingContext.HeritageClauses:
2349                // This would probably be safe to reuse.  There is no speculative parsing with
2350                // heritage clauses.
2351
2352                // case ParsingContext.TypeParameters:
2353                // This would probably be safe to reuse.  There is no speculative parsing with
2354                // type parameters.  Note that that's because type *parameters* only occur in
2355                // unambiguous *type* contexts.  While type *arguments* occur in very ambiguous
2356                // *expression* contexts.
2357
2358                // case ParsingContext.TupleElementTypes:
2359                // This would probably be safe to reuse.  There is no speculative parsing with
2360                // tuple types.
2361
2362                // Technically, type argument list types are probably safe to reuse.  While
2363                // speculative parsing is involved with them (since type argument lists are only
2364                // produced from speculative parsing a < as a type argument list), we only have
2365                // the types because speculative parsing succeeded.  Thus, the lookahead never
2366                // went past the end of the list and rewound.
2367                // case ParsingContext.TypeArguments:
2368
2369                // Note: these are almost certainly not safe to ever reuse.  Expressions commonly
2370                // need a large amount of lookahead, and we should not reuse them as they may
2371                // have actually intersected the edit.
2372                // case ParsingContext.ArgumentExpressions:
2373
2374                // This is not safe to reuse for the same reason as the 'AssignmentExpression'
2375                // cases.  i.e. a property assignment may end with an expression, and thus might
2376                // have lookahead far beyond it's old node.
2377                // case ParsingContext.ObjectLiteralMembers:
2378
2379                // This is probably not safe to reuse.  There can be speculative parsing with
2380                // type names in a heritage clause.  There can be generic names in the type
2381                // name list, and there can be left hand side expressions (which can have type
2382                // arguments.)
2383                // case ParsingContext.HeritageClauseElement:
2384
2385                // Perhaps safe to reuse, but it's unlikely we'd see more than a dozen attributes
2386                // on any given element. Same for children.
2387                // case ParsingContext.JsxAttributes:
2388                // case ParsingContext.JsxChildren:
2389
2390            }
2391
2392            return false;
2393        }
2394
2395        function isReusableClassMember(node: Node) {
2396            if (node) {
2397                switch (node.kind) {
2398                    case SyntaxKind.Constructor:
2399                    case SyntaxKind.IndexSignature:
2400                    case SyntaxKind.GetAccessor:
2401                    case SyntaxKind.SetAccessor:
2402                    case SyntaxKind.SemicolonClassElement:
2403                        return true;
2404                    case SyntaxKind.PropertyDeclaration:
2405                        return !inStructContext();
2406                    case SyntaxKind.MethodDeclaration:
2407                        // Method declarations are not necessarily reusable.  An object-literal
2408                        // may have a method calls "constructor(...)" and we must reparse that
2409                        // into an actual .ConstructorDeclaration.
2410                        const methodDeclaration = <MethodDeclaration>node;
2411                        const nameIsConstructor = methodDeclaration.name.kind === SyntaxKind.Identifier &&
2412                            methodDeclaration.name.originalKeywordKind === SyntaxKind.ConstructorKeyword;
2413
2414                        return !nameIsConstructor;
2415                }
2416            }
2417
2418            return false;
2419        }
2420
2421        function isReusableSwitchClause(node: Node) {
2422            if (node) {
2423                switch (node.kind) {
2424                    case SyntaxKind.CaseClause:
2425                    case SyntaxKind.DefaultClause:
2426                        return true;
2427                }
2428            }
2429
2430            return false;
2431        }
2432
2433        function isReusableStatement(node: Node) {
2434            if (node) {
2435                switch (node.kind) {
2436                    case SyntaxKind.FunctionDeclaration:
2437                    case SyntaxKind.VariableStatement:
2438                    case SyntaxKind.Block:
2439                    case SyntaxKind.IfStatement:
2440                    case SyntaxKind.ExpressionStatement:
2441                    case SyntaxKind.ThrowStatement:
2442                    case SyntaxKind.ReturnStatement:
2443                    case SyntaxKind.SwitchStatement:
2444                    case SyntaxKind.BreakStatement:
2445                    case SyntaxKind.ContinueStatement:
2446                    case SyntaxKind.ForInStatement:
2447                    case SyntaxKind.ForOfStatement:
2448                    case SyntaxKind.ForStatement:
2449                    case SyntaxKind.WhileStatement:
2450                    case SyntaxKind.WithStatement:
2451                    case SyntaxKind.EmptyStatement:
2452                    case SyntaxKind.TryStatement:
2453                    case SyntaxKind.LabeledStatement:
2454                    case SyntaxKind.DoStatement:
2455                    case SyntaxKind.DebuggerStatement:
2456                    case SyntaxKind.ImportDeclaration:
2457                    case SyntaxKind.ImportEqualsDeclaration:
2458                    case SyntaxKind.ExportDeclaration:
2459                    case SyntaxKind.ExportAssignment:
2460                    case SyntaxKind.ModuleDeclaration:
2461                    case SyntaxKind.ClassDeclaration:
2462                    case SyntaxKind.StructDeclaration:
2463                    case SyntaxKind.InterfaceDeclaration:
2464                    case SyntaxKind.EnumDeclaration:
2465                    case SyntaxKind.TypeAliasDeclaration:
2466                        return true;
2467                }
2468            }
2469
2470            return false;
2471        }
2472
2473        function isReusableEnumMember(node: Node) {
2474            return node.kind === SyntaxKind.EnumMember;
2475        }
2476
2477        function isReusableTypeMember(node: Node) {
2478            if (node) {
2479                switch (node.kind) {
2480                    case SyntaxKind.ConstructSignature:
2481                    case SyntaxKind.MethodSignature:
2482                    case SyntaxKind.IndexSignature:
2483                    case SyntaxKind.PropertySignature:
2484                    case SyntaxKind.CallSignature:
2485                        return true;
2486                }
2487            }
2488
2489            return false;
2490        }
2491
2492        function isReusableVariableDeclaration(node: Node) {
2493            if (node.kind !== SyntaxKind.VariableDeclaration) {
2494                return false;
2495            }
2496
2497            // Very subtle incremental parsing bug.  Consider the following code:
2498            //
2499            //      let v = new List < A, B
2500            //
2501            // This is actually legal code.  It's a list of variable declarators "v = new List<A"
2502            // on one side and "B" on the other. If you then change that to:
2503            //
2504            //      let v = new List < A, B >()
2505            //
2506            // then we have a problem.  "v = new List<A" doesn't intersect the change range, so we
2507            // start reparsing at "B" and we completely fail to handle this properly.
2508            //
2509            // In order to prevent this, we do not allow a variable declarator to be reused if it
2510            // has an initializer.
2511            const variableDeclarator = <VariableDeclaration>node;
2512            return variableDeclarator.initializer === undefined;
2513        }
2514
2515        function isReusableParameter(node: Node) {
2516            if (node.kind !== SyntaxKind.Parameter) {
2517                return false;
2518            }
2519
2520            // See the comment in isReusableVariableDeclaration for why we do this.
2521            const parameter = <ParameterDeclaration>node;
2522            return parameter.initializer === undefined;
2523        }
2524
2525        // Returns true if we should abort parsing.
2526        function abortParsingListOrMoveToNextToken(kind: ParsingContext) {
2527            parsingContextErrors(kind);
2528            if (isInSomeParsingContext()) {
2529                return true;
2530            }
2531
2532            nextToken();
2533            return false;
2534        }
2535
2536        function parsingContextErrors(context: ParsingContext) {
2537            switch (context) {
2538                case ParsingContext.SourceElements: return parseErrorAtCurrentToken(Diagnostics.Declaration_or_statement_expected);
2539                case ParsingContext.BlockStatements: return parseErrorAtCurrentToken(Diagnostics.Declaration_or_statement_expected);
2540                case ParsingContext.SwitchClauses: return parseErrorAtCurrentToken(Diagnostics.case_or_default_expected);
2541                case ParsingContext.SwitchClauseStatements: return parseErrorAtCurrentToken(Diagnostics.Statement_expected);
2542                case ParsingContext.RestProperties: // fallthrough
2543                case ParsingContext.TypeMembers: return parseErrorAtCurrentToken(Diagnostics.Property_or_signature_expected);
2544                case ParsingContext.ClassMembers: return parseErrorAtCurrentToken(Diagnostics.Unexpected_token_A_constructor_method_accessor_or_property_was_expected);
2545                case ParsingContext.EnumMembers: return parseErrorAtCurrentToken(Diagnostics.Enum_member_expected);
2546                case ParsingContext.HeritageClauseElement: return parseErrorAtCurrentToken(Diagnostics.Expression_expected);
2547                case ParsingContext.VariableDeclarations:
2548                    return isKeyword(token())
2549                        ? parseErrorAtCurrentToken(Diagnostics._0_is_not_allowed_as_a_variable_declaration_name, tokenToString(token()))
2550                        : parseErrorAtCurrentToken(Diagnostics.Variable_declaration_expected);
2551                case ParsingContext.ObjectBindingElements: return parseErrorAtCurrentToken(Diagnostics.Property_destructuring_pattern_expected);
2552                case ParsingContext.ArrayBindingElements: return parseErrorAtCurrentToken(Diagnostics.Array_element_destructuring_pattern_expected);
2553                case ParsingContext.ArgumentExpressions: return parseErrorAtCurrentToken(Diagnostics.Argument_expression_expected);
2554                case ParsingContext.ObjectLiteralMembers: return parseErrorAtCurrentToken(Diagnostics.Property_assignment_expected);
2555                case ParsingContext.ArrayLiteralMembers: return parseErrorAtCurrentToken(Diagnostics.Expression_or_comma_expected);
2556                case ParsingContext.JSDocParameters: return parseErrorAtCurrentToken(Diagnostics.Parameter_declaration_expected);
2557                case ParsingContext.Parameters: return parseErrorAtCurrentToken(Diagnostics.Parameter_declaration_expected);
2558                case ParsingContext.TypeParameters: return parseErrorAtCurrentToken(Diagnostics.Type_parameter_declaration_expected);
2559                case ParsingContext.TypeArguments: return parseErrorAtCurrentToken(Diagnostics.Type_argument_expected);
2560                case ParsingContext.TupleElementTypes: return parseErrorAtCurrentToken(Diagnostics.Type_expected);
2561                case ParsingContext.HeritageClauses: return parseErrorAtCurrentToken(Diagnostics.Unexpected_token_expected);
2562                case ParsingContext.ImportOrExportSpecifiers: return parseErrorAtCurrentToken(Diagnostics.Identifier_expected);
2563                case ParsingContext.JsxAttributes: return parseErrorAtCurrentToken(Diagnostics.Identifier_expected);
2564                case ParsingContext.JsxChildren: return parseErrorAtCurrentToken(Diagnostics.Identifier_expected);
2565                default: return [undefined!]; // TODO: GH#18217 `default: Debug.assertNever(context);`
2566            }
2567        }
2568
2569        // Parses a comma-delimited list of elements
2570        function parseDelimitedList<T extends Node>(kind: ParsingContext, parseElement: () => T, considerSemicolonAsDelimiter?: boolean): NodeArray<T> {
2571            const saveParsingContext = parsingContext;
2572            parsingContext |= 1 << kind;
2573            const list = [];
2574            const listPos = getNodePos();
2575
2576            let commaStart = -1; // Meaning the previous token was not a comma
2577            while (true) {
2578                if (isListElement(kind, /*inErrorRecovery*/ false)) {
2579                    const startPos = scanner.getStartPos();
2580                    list.push(parseListElement(kind, parseElement));
2581                    commaStart = scanner.getTokenPos();
2582
2583                    if (parseOptional(SyntaxKind.CommaToken)) {
2584                        // No need to check for a zero length node since we know we parsed a comma
2585                        continue;
2586                    }
2587
2588                    commaStart = -1; // Back to the state where the last token was not a comma
2589                    if (isListTerminator(kind)) {
2590                        break;
2591                    }
2592
2593                    // We didn't get a comma, and the list wasn't terminated, explicitly parse
2594                    // out a comma so we give a good error message.
2595                    parseExpected(SyntaxKind.CommaToken, getExpectedCommaDiagnostic(kind));
2596
2597                    // If the token was a semicolon, and the caller allows that, then skip it and
2598                    // continue.  This ensures we get back on track and don't result in tons of
2599                    // parse errors.  For example, this can happen when people do things like use
2600                    // a semicolon to delimit object literal members.   Note: we'll have already
2601                    // reported an error when we called parseExpected above.
2602                    if (considerSemicolonAsDelimiter && token() === SyntaxKind.SemicolonToken && !scanner.hasPrecedingLineBreak()) {
2603                        nextToken();
2604                    }
2605                    if (startPos === scanner.getStartPos()) {
2606                        // What we're parsing isn't actually remotely recognizable as a element and we've consumed no tokens whatsoever
2607                        // Consume a token to advance the parser in some way and avoid an infinite loop
2608                        // This can happen when we're speculatively parsing parenthesized expressions which we think may be arrow functions,
2609                        // or when a modifier keyword which is disallowed as a parameter name (ie, `static` in strict mode) is supplied
2610                        nextToken();
2611                    }
2612                    continue;
2613                }
2614
2615                if (isListTerminator(kind)) {
2616                    break;
2617                }
2618
2619                if (abortParsingListOrMoveToNextToken(kind)) {
2620                    break;
2621                }
2622            }
2623
2624            parsingContext = saveParsingContext;
2625            // Recording the trailing comma is deliberately done after the previous
2626            // loop, and not just if we see a list terminator. This is because the list
2627            // may have ended incorrectly, but it is still important to know if there
2628            // was a trailing comma.
2629            // Check if the last token was a comma.
2630            // Always preserve a trailing comma by marking it on the NodeArray
2631            return createNodeArray(list, listPos, /*end*/ undefined, commaStart >= 0);
2632        }
2633
2634        function getExpectedCommaDiagnostic(kind: ParsingContext) {
2635            return kind === ParsingContext.EnumMembers ? Diagnostics.An_enum_member_name_must_be_followed_by_a_or : undefined;
2636        }
2637
2638        interface MissingList<T extends Node> extends NodeArray<T> {
2639            isMissingList: true;
2640        }
2641
2642        function createMissingList<T extends Node>(): MissingList<T> {
2643            const list = createNodeArray<T>([], getNodePos()) as MissingList<T>;
2644            list.isMissingList = true;
2645            return list;
2646        }
2647
2648        function isMissingList(arr: NodeArray<Node>): boolean {
2649            return !!(arr as MissingList<Node>).isMissingList;
2650        }
2651
2652        function parseBracketedList<T extends Node>(kind: ParsingContext, parseElement: () => T, open: SyntaxKind, close: SyntaxKind): NodeArray<T> {
2653            if (parseExpected(open)) {
2654                const result = parseDelimitedList(kind, parseElement);
2655                parseExpected(close);
2656                return result;
2657            }
2658
2659            return createMissingList<T>();
2660        }
2661
2662        function parseEntityName(allowReservedWords: boolean, diagnosticMessage?: DiagnosticMessage): EntityName {
2663            const pos = getNodePos();
2664            let entity: EntityName = allowReservedWords ? parseIdentifierName(diagnosticMessage) : parseIdentifier(diagnosticMessage);
2665            let dotPos = getNodePos();
2666            while (parseOptional(SyntaxKind.DotToken)) {
2667                if (token() === SyntaxKind.LessThanToken) {
2668                    // the entity is part of a JSDoc-style generic, so record the trailing dot for later error reporting
2669                    entity.jsdocDotPos = dotPos;
2670                    break;
2671                }
2672                dotPos = getNodePos();
2673                entity = finishNode(
2674                    factory.createQualifiedName(
2675                        entity,
2676                        parseRightSideOfDot(allowReservedWords, /* allowPrivateIdentifiers */ false) as Identifier
2677                    ),
2678                    pos
2679                );
2680            }
2681            return entity;
2682        }
2683
2684        function createQualifiedName(entity: EntityName, name: Identifier): QualifiedName {
2685            return finishNode(factory.createQualifiedName(entity, name), entity.pos);
2686        }
2687
2688        function parseRightSideOfDot(allowIdentifierNames: boolean, allowPrivateIdentifiers: boolean): Identifier | PrivateIdentifier {
2689            // Technically a keyword is valid here as all identifiers and keywords are identifier names.
2690            // However, often we'll encounter this in error situations when the identifier or keyword
2691            // is actually starting another valid construct.
2692            //
2693            // So, we check for the following specific case:
2694            //
2695            //      name.
2696            //      identifierOrKeyword identifierNameOrKeyword
2697            //
2698            // Note: the newlines are important here.  For example, if that above code
2699            // were rewritten into:
2700            //
2701            //      name.identifierOrKeyword
2702            //      identifierNameOrKeyword
2703            //
2704            // Then we would consider it valid.  That's because ASI would take effect and
2705            // the code would be implicitly: "name.identifierOrKeyword; identifierNameOrKeyword".
2706            // In the first case though, ASI will not take effect because there is not a
2707            // line terminator after the identifier or keyword.
2708            if (scanner.hasPrecedingLineBreak() && tokenIsIdentifierOrKeyword(token())) {
2709                const matchesPattern = lookAhead(nextTokenIsIdentifierOrKeywordOnSameLine);
2710
2711                if (matchesPattern) {
2712                    // Report that we need an identifier.  However, report it right after the dot,
2713                    // and not on the next token.  This is because the next token might actually
2714                    // be an identifier and the error would be quite confusing.
2715                    return createMissingNode<Identifier>(SyntaxKind.Identifier, /*reportAtCurrentPosition*/ true, Diagnostics.Identifier_expected);
2716                }
2717            }
2718
2719            if (token() === SyntaxKind.PrivateIdentifier) {
2720                const node = parsePrivateIdentifier();
2721                return allowPrivateIdentifiers ? node : createMissingNode<Identifier>(SyntaxKind.Identifier, /*reportAtCurrentPosition*/ true, Diagnostics.Identifier_expected);
2722            }
2723
2724            return allowIdentifierNames ? parseIdentifierName() : parseIdentifier();
2725        }
2726
2727        function parseTemplateSpans(isTaggedTemplate: boolean) {
2728            const pos = getNodePos();
2729            const list = [];
2730            let node: TemplateSpan;
2731            do {
2732                node = parseTemplateSpan(isTaggedTemplate);
2733                list.push(node);
2734            }
2735            while (node.literal.kind === SyntaxKind.TemplateMiddle);
2736            return createNodeArray(list, pos);
2737        }
2738
2739        function parseTemplateExpression(isTaggedTemplate: boolean): TemplateExpression {
2740            const pos = getNodePos();
2741            return finishNode(
2742                factory.createTemplateExpression(
2743                    parseTemplateHead(isTaggedTemplate),
2744                    parseTemplateSpans(isTaggedTemplate)
2745                ),
2746                pos
2747            );
2748        }
2749
2750        function parseTemplateType(): TemplateLiteralTypeNode {
2751            const pos = getNodePos();
2752            return finishNode(
2753                factory.createTemplateLiteralType(
2754                    parseTemplateHead(/*isTaggedTemplate*/ false),
2755                    parseTemplateTypeSpans()
2756                ),
2757                pos
2758            );
2759        }
2760
2761        function parseTemplateTypeSpans() {
2762            const pos = getNodePos();
2763            const list = [];
2764            let node: TemplateLiteralTypeSpan;
2765            do {
2766                node = parseTemplateTypeSpan();
2767                list.push(node);
2768            }
2769            while (node.literal.kind === SyntaxKind.TemplateMiddle);
2770            return createNodeArray(list, pos);
2771        }
2772
2773        function parseTemplateTypeSpan(): TemplateLiteralTypeSpan {
2774            const pos = getNodePos();
2775            return finishNode(
2776                factory.createTemplateLiteralTypeSpan(
2777                    parseType(),
2778                    parseLiteralOfTemplateSpan(/*isTaggedTemplate*/ false)
2779                ),
2780                pos
2781            );
2782        }
2783
2784        function parseLiteralOfTemplateSpan(isTaggedTemplate: boolean) {
2785            if (token() === SyntaxKind.CloseBraceToken) {
2786                reScanTemplateToken(isTaggedTemplate);
2787                return parseTemplateMiddleOrTemplateTail();
2788            }
2789            else {
2790                // TODO(rbuckton): Do we need to call `parseExpectedToken` or can we just call `createMissingNode` directly?
2791                return <TemplateTail>parseExpectedToken(SyntaxKind.TemplateTail, Diagnostics._0_expected, tokenToString(SyntaxKind.CloseBraceToken));
2792            }
2793        }
2794
2795        function parseTemplateSpan(isTaggedTemplate: boolean): TemplateSpan {
2796            const pos = getNodePos();
2797            return finishNode(
2798                factory.createTemplateSpan(
2799                    allowInAnd(parseExpression),
2800                    parseLiteralOfTemplateSpan(isTaggedTemplate)
2801                ),
2802                pos
2803            );
2804        }
2805
2806        function parseLiteralNode(): LiteralExpression {
2807            return <LiteralExpression>parseLiteralLikeNode(token());
2808        }
2809
2810        function parseTemplateHead(isTaggedTemplate: boolean): TemplateHead {
2811            if (isTaggedTemplate) {
2812                reScanTemplateHeadOrNoSubstitutionTemplate();
2813            }
2814            const fragment = parseLiteralLikeNode(token());
2815            Debug.assert(fragment.kind === SyntaxKind.TemplateHead, "Template head has wrong token kind");
2816            return <TemplateHead>fragment;
2817        }
2818
2819        function parseTemplateMiddleOrTemplateTail(): TemplateMiddle | TemplateTail {
2820            const fragment = parseLiteralLikeNode(token());
2821            Debug.assert(fragment.kind === SyntaxKind.TemplateMiddle || fragment.kind === SyntaxKind.TemplateTail, "Template fragment has wrong token kind");
2822            return <TemplateMiddle | TemplateTail>fragment;
2823        }
2824
2825        function getTemplateLiteralRawText(kind: TemplateLiteralToken["kind"]) {
2826            const isLast = kind === SyntaxKind.NoSubstitutionTemplateLiteral || kind === SyntaxKind.TemplateTail;
2827            const tokenText = scanner.getTokenText();
2828            return tokenText.substring(1, tokenText.length - (scanner.isUnterminated() ? 0 : isLast ? 1 : 2));
2829        }
2830
2831        function parseLiteralLikeNode(kind: SyntaxKind): LiteralLikeNode {
2832            const pos = getNodePos();
2833            const node =
2834                isTemplateLiteralKind(kind) ? factory.createTemplateLiteralLikeNode(kind, scanner.getTokenValue(), getTemplateLiteralRawText(kind), scanner.getTokenFlags() & TokenFlags.TemplateLiteralLikeFlags) :
2835                // Octal literals are not allowed in strict mode or ES5
2836                // Note that theoretically the following condition would hold true literals like 009,
2837                // which is not octal. But because of how the scanner separates the tokens, we would
2838                // never get a token like this. Instead, we would get 00 and 9 as two separate tokens.
2839                // We also do not need to check for negatives because any prefix operator would be part of a
2840                // parent unary expression.
2841                kind === SyntaxKind.NumericLiteral ? factory.createNumericLiteral(scanner.getTokenValue(), scanner.getNumericLiteralFlags()) :
2842                kind === SyntaxKind.StringLiteral ? factory.createStringLiteral(scanner.getTokenValue(), /*isSingleQuote*/ undefined, scanner.hasExtendedUnicodeEscape()) :
2843                isLiteralKind(kind) ? factory.createLiteralLikeNode(kind, scanner.getTokenValue()) :
2844                Debug.fail();
2845
2846            if (scanner.hasExtendedUnicodeEscape()) {
2847                node.hasExtendedUnicodeEscape = true;
2848            }
2849
2850            if (scanner.isUnterminated()) {
2851                node.isUnterminated = true;
2852            }
2853
2854            nextToken();
2855            return finishNode(node, pos);
2856        }
2857
2858        // TYPES
2859
2860        function parseEntityNameOfTypeReference() {
2861            return parseEntityName(/*allowReservedWords*/ true, Diagnostics.Type_expected);
2862        }
2863
2864        function parseTypeArgumentsOfTypeReference() {
2865            if (!scanner.hasPrecedingLineBreak() && reScanLessThanToken() === SyntaxKind.LessThanToken) {
2866                return parseBracketedList(ParsingContext.TypeArguments, parseType, SyntaxKind.LessThanToken, SyntaxKind.GreaterThanToken);
2867            }
2868        }
2869
2870        function parseTypeReference(): TypeReferenceNode {
2871            const pos = getNodePos();
2872            return finishNode(
2873                factory.createTypeReferenceNode(
2874                    parseEntityNameOfTypeReference(),
2875                    parseTypeArgumentsOfTypeReference()
2876                ),
2877                pos
2878            );
2879        }
2880
2881        // If true, we should abort parsing an error function.
2882        function typeHasArrowFunctionBlockingParseError(node: TypeNode): boolean {
2883            switch (node.kind) {
2884                case SyntaxKind.TypeReference:
2885                    return nodeIsMissing((node as TypeReferenceNode).typeName);
2886                case SyntaxKind.FunctionType:
2887                case SyntaxKind.ConstructorType: {
2888                    const { parameters, type } = node as FunctionOrConstructorTypeNode;
2889                    return isMissingList(parameters) || typeHasArrowFunctionBlockingParseError(type);
2890                }
2891                case SyntaxKind.ParenthesizedType:
2892                    return typeHasArrowFunctionBlockingParseError((node as ParenthesizedTypeNode).type);
2893                default:
2894                    return false;
2895            }
2896        }
2897
2898        function parseThisTypePredicate(lhs: ThisTypeNode): TypePredicateNode {
2899            nextToken();
2900            return finishNode(factory.createTypePredicateNode(/*assertsModifier*/ undefined, lhs, parseType()), lhs.pos);
2901        }
2902
2903        function parseThisTypeNode(): ThisTypeNode {
2904            const pos = getNodePos();
2905            nextToken();
2906            return finishNode(factory.createThisTypeNode(), pos);
2907        }
2908
2909        function parseJSDocAllType(): JSDocAllType | JSDocOptionalType {
2910            const pos = getNodePos();
2911            nextToken();
2912            return finishNode(factory.createJSDocAllType(), pos);
2913        }
2914
2915        function parseJSDocNonNullableType(): TypeNode {
2916            const pos = getNodePos();
2917            nextToken();
2918            return finishNode(factory.createJSDocNonNullableType(parseNonArrayType()), pos);
2919        }
2920
2921        function parseJSDocUnknownOrNullableType(): JSDocUnknownType | JSDocNullableType {
2922            const pos = getNodePos();
2923            // skip the ?
2924            nextToken();
2925
2926            // Need to lookahead to decide if this is a nullable or unknown type.
2927
2928            // Here are cases where we'll pick the unknown type:
2929            //
2930            //      Foo(?,
2931            //      { a: ? }
2932            //      Foo(?)
2933            //      Foo<?>
2934            //      Foo(?=
2935            //      (?|
2936            if (token() === SyntaxKind.CommaToken ||
2937                token() === SyntaxKind.CloseBraceToken ||
2938                token() === SyntaxKind.CloseParenToken ||
2939                token() === SyntaxKind.GreaterThanToken ||
2940                token() === SyntaxKind.EqualsToken ||
2941                token() === SyntaxKind.BarToken) {
2942                return finishNode(factory.createJSDocUnknownType(), pos);
2943            }
2944            else {
2945                return finishNode(factory.createJSDocNullableType(parseType()), pos);
2946            }
2947        }
2948
2949        function parseJSDocFunctionType(): JSDocFunctionType | TypeReferenceNode {
2950            const pos = getNodePos();
2951            const hasJSDoc = hasPrecedingJSDocComment();
2952            if (lookAhead(nextTokenIsOpenParen)) {
2953                nextToken();
2954                const parameters = parseParameters(SignatureFlags.Type | SignatureFlags.JSDoc);
2955                const type = parseReturnType(SyntaxKind.ColonToken, /*isType*/ false);
2956                return withJSDoc(finishNode(factory.createJSDocFunctionType(parameters, type), pos), hasJSDoc);
2957            }
2958            return finishNode(factory.createTypeReferenceNode(parseIdentifierName(), /*typeArguments*/ undefined), pos);
2959        }
2960
2961        function parseJSDocParameter(): ParameterDeclaration {
2962            const pos = getNodePos();
2963            let name: Identifier | undefined;
2964            if (token() === SyntaxKind.ThisKeyword || token() === SyntaxKind.NewKeyword) {
2965                name = parseIdentifierName();
2966                parseExpected(SyntaxKind.ColonToken);
2967            }
2968            return finishNode(
2969                factory.createParameterDeclaration(
2970                    /*decorators*/ undefined,
2971                    /*modifiers*/ undefined,
2972                    /*dotDotDotToken*/ undefined,
2973                    // TODO(rbuckton): JSDoc parameters don't have names (except `this`/`new`), should we manufacture an empty identifier?
2974                    name!,
2975                    /*questionToken*/ undefined,
2976                    parseJSDocType(),
2977                    /*initializer*/ undefined
2978                ),
2979                pos
2980            );
2981        }
2982
2983        function parseJSDocType(): TypeNode {
2984            scanner.setInJSDocType(true);
2985            const pos = getNodePos();
2986            if (parseOptional(SyntaxKind.ModuleKeyword)) {
2987                // TODO(rbuckton): We never set the type for a JSDocNamepathType. What should we put here?
2988                const moduleTag = factory.createJSDocNamepathType(/*type*/ undefined!);
2989                terminate: while (true) {
2990                    switch (token()) {
2991                        case SyntaxKind.CloseBraceToken:
2992                        case SyntaxKind.EndOfFileToken:
2993                        case SyntaxKind.CommaToken:
2994                        case SyntaxKind.WhitespaceTrivia:
2995                            break terminate;
2996                        default:
2997                            nextTokenJSDoc();
2998                    }
2999                }
3000
3001                scanner.setInJSDocType(false);
3002                return finishNode(moduleTag, pos);
3003            }
3004
3005            const hasDotDotDot = parseOptional(SyntaxKind.DotDotDotToken);
3006            let type = parseTypeOrTypePredicate();
3007            scanner.setInJSDocType(false);
3008            if (hasDotDotDot) {
3009                type = finishNode(factory.createJSDocVariadicType(type), pos);
3010            }
3011            if (token() === SyntaxKind.EqualsToken) {
3012                nextToken();
3013                return finishNode(factory.createJSDocOptionalType(type), pos);
3014            }
3015            return type;
3016        }
3017
3018        function parseTypeQuery(): TypeQueryNode {
3019            const pos = getNodePos();
3020            parseExpected(SyntaxKind.TypeOfKeyword);
3021            return finishNode(factory.createTypeQueryNode(parseEntityName(/*allowReservedWords*/ true)), pos);
3022        }
3023
3024        function parseTypeParameter(position?: number): TypeParameterDeclaration {
3025            const pos = getNodePos();
3026            const name = position !== undefined ? parseEtsIdentifier(position) : parseIdentifier();
3027            let constraint: TypeNode | undefined;
3028            let expression: Expression | undefined;
3029            if (parseOptional(SyntaxKind.ExtendsKeyword)) {
3030                // It's not uncommon for people to write improper constraints to a generic.  If the
3031                // user writes a constraint that is an expression and not an actual type, then parse
3032                // it out as an expression (so we can recover well), but report that a type is needed
3033                // instead.
3034                if (isStartOfType() || !isStartOfExpression()) {
3035                    constraint = parseType();
3036                }
3037                else {
3038                    // It was not a type, and it looked like an expression.  Parse out an expression
3039                    // here so we recover well.  Note: it is important that we call parseUnaryExpression
3040                    // and not parseExpression here.  If the user has:
3041                    //
3042                    //      <T extends "">
3043                    //
3044                    // We do *not* want to consume the `>` as we're consuming the expression for "".
3045                    expression = parseUnaryExpressionOrHigher();
3046                }
3047            }
3048
3049            const defaultType = parseOptional(SyntaxKind.EqualsToken) ? parseType() : undefined;
3050            const node = factory.createTypeParameterDeclaration(name, constraint, defaultType);
3051            node.expression = expression;
3052            return position !== undefined ? finishVirtualNode(node, position, position) : finishNode(node, pos);
3053        }
3054
3055        function parseTypeParameters(): NodeArray<TypeParameterDeclaration> | undefined {
3056            if (token() === SyntaxKind.LessThanToken) {
3057                return parseBracketedList(ParsingContext.TypeParameters, parseTypeParameter, SyntaxKind.LessThanToken, SyntaxKind.GreaterThanToken);
3058            }
3059        }
3060
3061        function parseEtsTypeParameters(pos: number): NodeArray<TypeParameterDeclaration> | undefined {
3062            return createNodeArray([parseTypeParameter(pos)], getNodePos());
3063        }
3064
3065        function parseEtsTypeArguments(pos: number, name: string): NodeArray<TypeNode> | undefined {
3066            if ((contextFlags & NodeFlags.JavaScriptFile) !== 0) {
3067                // TypeArguments must not be parsed in JavaScript files to avoid ambiguity with binary operators.
3068                return undefined;
3069            }
3070
3071            return createNodeArray([parseEtsType(pos, name)], getNodePos());
3072        }
3073
3074        function isStartOfParameter(isJSDocParameter: boolean): boolean {
3075            return token() === SyntaxKind.DotDotDotToken ||
3076                isBindingIdentifierOrPrivateIdentifierOrPattern() ||
3077                isModifierKind(token()) ||
3078                token() === SyntaxKind.AtToken ||
3079                isStartOfType(/*inStartOfParameter*/ !isJSDocParameter);
3080        }
3081
3082        function parseNameOfParameter(modifiers: ModifiersArray | undefined) {
3083            // FormalParameter [Yield,Await]:
3084            //      BindingElement[?Yield,?Await]
3085            const name = parseIdentifierOrPattern(Diagnostics.Private_identifiers_cannot_be_used_as_parameters);
3086            if (getFullWidth(name) === 0 && !some(modifiers) && isModifierKind(token())) {
3087                // in cases like
3088                // 'use strict'
3089                // function foo(static)
3090                // isParameter('static') === true, because of isModifier('static')
3091                // however 'static' is not a legal identifier in a strict mode.
3092                // so result of this function will be ParameterDeclaration (flags = 0, name = missing, type = undefined, initializer = undefined)
3093                // and current token will not change => parsing of the enclosing parameter list will last till the end of time (or OOM)
3094                // to avoid this we'll advance cursor to the next token.
3095                nextToken();
3096            }
3097            return name;
3098        }
3099
3100        function parseParameterInOuterAwaitContext() {
3101            return parseParameterWorker(/*inOuterAwaitContext*/ true);
3102        }
3103
3104        function parseParameter(): ParameterDeclaration {
3105            return parseParameterWorker(/*inOuterAwaitContext*/ false);
3106        }
3107
3108        function parseParameterWorker(inOuterAwaitContext: boolean): ParameterDeclaration {
3109            const pos = getNodePos();
3110            const hasJSDoc = hasPrecedingJSDocComment();
3111            if (token() === SyntaxKind.ThisKeyword) {
3112                const node = factory.createParameterDeclaration(
3113                    /*decorators*/ undefined,
3114                    /*modifiers*/ undefined,
3115                    /*dotDotDotToken*/ undefined,
3116                    createIdentifier(/*isIdentifier*/ true),
3117                    /*questionToken*/ undefined,
3118                    parseTypeAnnotation(),
3119                    /*initializer*/ undefined
3120                );
3121                return withJSDoc(finishNode(node, pos), hasJSDoc);
3122            }
3123
3124            // FormalParameter [Yield,Await]:
3125            //      BindingElement[?Yield,?Await]
3126
3127            // Decorators are parsed in the outer [Await] context, the rest of the parameter is parsed in the function's [Await] context.
3128            const decorators = inOuterAwaitContext ? doInAwaitContext(parseDecorators) : parseDecorators();
3129            const savedTopLevel = topLevel;
3130            topLevel = false;
3131            const modifiers = parseModifiers();
3132            const node = withJSDoc(
3133                finishNode(
3134                    factory.createParameterDeclaration(
3135                        decorators,
3136                        modifiers,
3137                        parseOptionalToken(SyntaxKind.DotDotDotToken),
3138                        parseNameOfParameter(modifiers),
3139                        parseOptionalToken(SyntaxKind.QuestionToken),
3140                        parseTypeAnnotation(),
3141                        parseInitializer()
3142                    ),
3143                    pos
3144                ),
3145                hasJSDoc
3146            );
3147            topLevel = savedTopLevel;
3148            return node;
3149        }
3150
3151        function parseReturnType(returnToken: SyntaxKind.EqualsGreaterThanToken, isType: boolean): TypeNode;
3152        function parseReturnType(returnToken: SyntaxKind.ColonToken | SyntaxKind.EqualsGreaterThanToken, isType: boolean): TypeNode | undefined;
3153        function parseReturnType(returnToken: SyntaxKind.ColonToken | SyntaxKind.EqualsGreaterThanToken, isType: boolean) {
3154            if (shouldParseReturnType(returnToken, isType)) {
3155                return parseTypeOrTypePredicate();
3156            }
3157        }
3158
3159        function shouldParseReturnType(returnToken: SyntaxKind.ColonToken | SyntaxKind.EqualsGreaterThanToken, isType: boolean): boolean {
3160            if (returnToken === SyntaxKind.EqualsGreaterThanToken) {
3161                parseExpected(returnToken);
3162                return true;
3163            }
3164            else if (parseOptional(SyntaxKind.ColonToken)) {
3165                return true;
3166            }
3167            else if (isType && token() === SyntaxKind.EqualsGreaterThanToken) {
3168                // This is easy to get backward, especially in type contexts, so parse the type anyway
3169                parseErrorAtCurrentToken(Diagnostics._0_expected, tokenToString(SyntaxKind.ColonToken));
3170                nextToken();
3171                return true;
3172            }
3173            return false;
3174        }
3175
3176        function parseParametersWorker(flags: SignatureFlags) {
3177            // FormalParameters [Yield,Await]: (modified)
3178            //      [empty]
3179            //      FormalParameterList[?Yield,Await]
3180            //
3181            // FormalParameter[Yield,Await]: (modified)
3182            //      BindingElement[?Yield,Await]
3183            //
3184            // BindingElement [Yield,Await]: (modified)
3185            //      SingleNameBinding[?Yield,?Await]
3186            //      BindingPattern[?Yield,?Await]Initializer [In, ?Yield,?Await] opt
3187            //
3188            // SingleNameBinding [Yield,Await]:
3189            //      BindingIdentifier[?Yield,?Await]Initializer [In, ?Yield,?Await] opt
3190            const savedYieldContext = inYieldContext();
3191            const savedAwaitContext = inAwaitContext();
3192
3193            setYieldContext(!!(flags & SignatureFlags.Yield));
3194            setAwaitContext(!!(flags & SignatureFlags.Await));
3195
3196            const parameters = flags & SignatureFlags.JSDoc ?
3197                parseDelimitedList(ParsingContext.JSDocParameters, parseJSDocParameter) :
3198                parseDelimitedList(ParsingContext.Parameters, savedAwaitContext ? parseParameterInOuterAwaitContext : parseParameter);
3199
3200            setYieldContext(savedYieldContext);
3201            setAwaitContext(savedAwaitContext);
3202
3203            return parameters;
3204        }
3205
3206        function parseParameters(flags: SignatureFlags): NodeArray<ParameterDeclaration> {
3207            // FormalParameters [Yield,Await]: (modified)
3208            //      [empty]
3209            //      FormalParameterList[?Yield,Await]
3210            //
3211            // FormalParameter[Yield,Await]: (modified)
3212            //      BindingElement[?Yield,Await]
3213            //
3214            // BindingElement [Yield,Await]: (modified)
3215            //      SingleNameBinding[?Yield,?Await]
3216            //      BindingPattern[?Yield,?Await]Initializer [In, ?Yield,?Await] opt
3217            //
3218            // SingleNameBinding [Yield,Await]:
3219            //      BindingIdentifier[?Yield,?Await]Initializer [In, ?Yield,?Await] opt
3220            if (!parseExpected(SyntaxKind.OpenParenToken)) {
3221                return createMissingList<ParameterDeclaration>();
3222            }
3223
3224            const parameters = parseParametersWorker(flags);
3225            parseExpected(SyntaxKind.CloseParenToken);
3226            return parameters;
3227        }
3228
3229        function parseTypeMemberSemicolon() {
3230            // We allow type members to be separated by commas or (possibly ASI) semicolons.
3231            // First check if it was a comma.  If so, we're done with the member.
3232            if (parseOptional(SyntaxKind.CommaToken)) {
3233                return;
3234            }
3235
3236            // Didn't have a comma.  We must have a (possible ASI) semicolon.
3237            parseSemicolon();
3238        }
3239
3240        function parseSignatureMember(kind: SyntaxKind.CallSignature | SyntaxKind.ConstructSignature): CallSignatureDeclaration | ConstructSignatureDeclaration {
3241            const pos = getNodePos();
3242            const hasJSDoc = hasPrecedingJSDocComment();
3243            if (kind === SyntaxKind.ConstructSignature) {
3244                parseExpected(SyntaxKind.NewKeyword);
3245            }
3246
3247            const typeParameters = parseTypeParameters();
3248            const parameters = parseParameters(SignatureFlags.Type);
3249            const type = parseReturnType(SyntaxKind.ColonToken, /*isType*/ true);
3250            parseTypeMemberSemicolon();
3251            const node = kind === SyntaxKind.CallSignature
3252                ? factory.createCallSignature(typeParameters, parameters, type)
3253                : factory.createConstructSignature(typeParameters, parameters, type);
3254            return withJSDoc(finishNode(node, pos), hasJSDoc);
3255        }
3256
3257        function isIndexSignature(): boolean {
3258            return token() === SyntaxKind.OpenBracketToken && lookAhead(isUnambiguouslyIndexSignature);
3259        }
3260
3261        function isUnambiguouslyIndexSignature() {
3262            // The only allowed sequence is:
3263            //
3264            //   [id:
3265            //
3266            // However, for error recovery, we also check the following cases:
3267            //
3268            //   [...
3269            //   [id,
3270            //   [id?,
3271            //   [id?:
3272            //   [id?]
3273            //   [public id
3274            //   [private id
3275            //   [protected id
3276            //   []
3277            //
3278            nextToken();
3279            if (token() === SyntaxKind.DotDotDotToken || token() === SyntaxKind.CloseBracketToken) {
3280                return true;
3281            }
3282
3283            if (isModifierKind(token())) {
3284                nextToken();
3285                if (isIdentifier()) {
3286                    return true;
3287                }
3288            }
3289            else if (!isIdentifier()) {
3290                return false;
3291            }
3292            else {
3293                // Skip the identifier
3294                nextToken();
3295            }
3296
3297            // A colon signifies a well formed indexer
3298            // A comma should be a badly formed indexer because comma expressions are not allowed
3299            // in computed properties.
3300            if (token() === SyntaxKind.ColonToken || token() === SyntaxKind.CommaToken) {
3301                return true;
3302            }
3303
3304            // Question mark could be an indexer with an optional property,
3305            // or it could be a conditional expression in a computed property.
3306            if (token() !== SyntaxKind.QuestionToken) {
3307                return false;
3308            }
3309
3310            // If any of the following tokens are after the question mark, it cannot
3311            // be a conditional expression, so treat it as an indexer.
3312            nextToken();
3313            return token() === SyntaxKind.ColonToken || token() === SyntaxKind.CommaToken || token() === SyntaxKind.CloseBracketToken;
3314        }
3315
3316        function parseIndexSignatureDeclaration(pos: number, hasJSDoc: boolean, decorators: NodeArray<Decorator> | undefined, modifiers: NodeArray<Modifier> | undefined): IndexSignatureDeclaration {
3317            const parameters = parseBracketedList(ParsingContext.Parameters, parseParameter, SyntaxKind.OpenBracketToken, SyntaxKind.CloseBracketToken);
3318            const type = parseTypeAnnotation();
3319            parseTypeMemberSemicolon();
3320            const node = factory.createIndexSignature(decorators, modifiers, parameters, type);
3321            return withJSDoc(finishNode(node, pos), hasJSDoc);
3322        }
3323
3324        function parsePropertyOrMethodSignature(pos: number, hasJSDoc: boolean, modifiers: NodeArray<Modifier> | undefined): PropertySignature | MethodSignature {
3325            const name = parsePropertyName();
3326            const questionToken = parseOptionalToken(SyntaxKind.QuestionToken);
3327            let node: PropertySignature | MethodSignature;
3328            if (token() === SyntaxKind.OpenParenToken || token() === SyntaxKind.LessThanToken) {
3329                // Method signatures don't exist in expression contexts.  So they have neither
3330                // [Yield] nor [Await]
3331                const typeParameters = parseTypeParameters();
3332                const parameters = parseParameters(SignatureFlags.Type);
3333                const type = parseReturnType(SyntaxKind.ColonToken, /*isType*/ true);
3334                node = factory.createMethodSignature(modifiers, name, questionToken, typeParameters, parameters, type);
3335            }
3336            else {
3337                const type = parseTypeAnnotation();
3338                node = factory.createPropertySignature(modifiers, name, questionToken, type);
3339                // Although type literal properties cannot not have initializers, we attempt
3340                // to parse an initializer so we can report in the checker that an interface
3341                // property or type literal property cannot have an initializer.
3342                if (token() === SyntaxKind.EqualsToken) node.initializer = parseInitializer();
3343            }
3344            parseTypeMemberSemicolon();
3345            return withJSDoc(finishNode(node, pos), hasJSDoc);
3346        }
3347
3348        function isTypeMemberStart(): boolean {
3349            // Return true if we have the start of a signature member
3350            if (token() === SyntaxKind.OpenParenToken || token() === SyntaxKind.LessThanToken) {
3351                return true;
3352            }
3353            let idToken = false;
3354            // Eat up all modifiers, but hold on to the last one in case it is actually an identifier
3355            while (isModifierKind(token())) {
3356                idToken = true;
3357                nextToken();
3358            }
3359            // Index signatures and computed property names are type members
3360            if (token() === SyntaxKind.OpenBracketToken) {
3361                return true;
3362            }
3363            // Try to get the first property-like token following all modifiers
3364            if (isLiteralPropertyName()) {
3365                idToken = true;
3366                nextToken();
3367            }
3368            // If we were able to get any potential identifier, check that it is
3369            // the start of a member declaration
3370            if (idToken) {
3371                return token() === SyntaxKind.OpenParenToken ||
3372                    token() === SyntaxKind.LessThanToken ||
3373                    token() === SyntaxKind.QuestionToken ||
3374                    token() === SyntaxKind.ColonToken ||
3375                    token() === SyntaxKind.CommaToken ||
3376                    canParseSemicolon();
3377            }
3378            return false;
3379        }
3380
3381        function parseTypeMember(): TypeElement {
3382            if (token() === SyntaxKind.OpenParenToken || token() === SyntaxKind.LessThanToken) {
3383                return parseSignatureMember(SyntaxKind.CallSignature);
3384            }
3385            if (token() === SyntaxKind.NewKeyword && lookAhead(nextTokenIsOpenParenOrLessThan)) {
3386                return parseSignatureMember(SyntaxKind.ConstructSignature);
3387            }
3388            const pos = getNodePos();
3389            const hasJSDoc = hasPrecedingJSDocComment();
3390            const modifiers = parseModifiers();
3391            if (isIndexSignature()) {
3392                return parseIndexSignatureDeclaration(pos, hasJSDoc, /*decorators*/ undefined, modifiers);
3393            }
3394            return parsePropertyOrMethodSignature(pos, hasJSDoc, modifiers);
3395        }
3396
3397        function nextTokenIsOpenParenOrLessThan() {
3398            nextToken();
3399            return token() === SyntaxKind.OpenParenToken || token() === SyntaxKind.LessThanToken;
3400        }
3401
3402        function nextTokenIsDot() {
3403            return nextToken() === SyntaxKind.DotToken;
3404        }
3405
3406        function nextTokenIsOpenParenOrLessThanOrDot() {
3407            switch (nextToken()) {
3408                case SyntaxKind.OpenParenToken:
3409                case SyntaxKind.LessThanToken:
3410                case SyntaxKind.DotToken:
3411                    return true;
3412            }
3413            return false;
3414        }
3415
3416        function parseTypeLiteral(): TypeLiteralNode {
3417            const pos = getNodePos();
3418            return finishNode(factory.createTypeLiteralNode(parseObjectTypeMembers()), pos);
3419        }
3420
3421        function parseObjectTypeMembers(): NodeArray<TypeElement> {
3422            let members: NodeArray<TypeElement>;
3423            if (parseExpected(SyntaxKind.OpenBraceToken)) {
3424                members = parseList(ParsingContext.TypeMembers, parseTypeMember);
3425                parseExpected(SyntaxKind.CloseBraceToken);
3426            }
3427            else {
3428                members = createMissingList<TypeElement>();
3429            }
3430
3431            return members;
3432        }
3433
3434        function isStartOfMappedType() {
3435            nextToken();
3436            if (token() === SyntaxKind.PlusToken || token() === SyntaxKind.MinusToken) {
3437                return nextToken() === SyntaxKind.ReadonlyKeyword;
3438            }
3439            if (token() === SyntaxKind.ReadonlyKeyword) {
3440                nextToken();
3441            }
3442            return token() === SyntaxKind.OpenBracketToken && nextTokenIsIdentifier() && nextToken() === SyntaxKind.InKeyword;
3443        }
3444
3445        function parseMappedTypeParameter() {
3446            const pos = getNodePos();
3447            const name = parseIdentifierName();
3448            parseExpected(SyntaxKind.InKeyword);
3449            const type = parseType();
3450            return finishNode(factory.createTypeParameterDeclaration(name, type, /*defaultType*/ undefined), pos);
3451        }
3452
3453        function parseMappedType() {
3454            const pos = getNodePos();
3455            parseExpected(SyntaxKind.OpenBraceToken);
3456            let readonlyToken: ReadonlyKeyword | PlusToken | MinusToken | undefined;
3457            if (token() === SyntaxKind.ReadonlyKeyword || token() === SyntaxKind.PlusToken || token() === SyntaxKind.MinusToken) {
3458                readonlyToken = parseTokenNode<ReadonlyKeyword | PlusToken | MinusToken>();
3459                if (readonlyToken.kind !== SyntaxKind.ReadonlyKeyword) {
3460                    parseExpected(SyntaxKind.ReadonlyKeyword);
3461                }
3462            }
3463            parseExpected(SyntaxKind.OpenBracketToken);
3464            const typeParameter = parseMappedTypeParameter();
3465            const nameType = parseOptional(SyntaxKind.AsKeyword) ? parseType() : undefined;
3466            parseExpected(SyntaxKind.CloseBracketToken);
3467            let questionToken: QuestionToken | PlusToken | MinusToken | undefined;
3468            if (token() === SyntaxKind.QuestionToken || token() === SyntaxKind.PlusToken || token() === SyntaxKind.MinusToken) {
3469                questionToken = parseTokenNode<QuestionToken | PlusToken | MinusToken>();
3470                if (questionToken.kind !== SyntaxKind.QuestionToken) {
3471                    parseExpected(SyntaxKind.QuestionToken);
3472                }
3473            }
3474            const type = parseTypeAnnotation();
3475            parseSemicolon();
3476            parseExpected(SyntaxKind.CloseBraceToken);
3477            return finishNode(factory.createMappedTypeNode(readonlyToken, typeParameter, nameType, questionToken, type), pos);
3478        }
3479
3480        function parseTupleElementType() {
3481            const pos = getNodePos();
3482            if (parseOptional(SyntaxKind.DotDotDotToken)) {
3483                return finishNode(factory.createRestTypeNode(parseType()), pos);
3484            }
3485            const type = parseType();
3486            if (isJSDocNullableType(type) && type.pos === type.type.pos) {
3487                const node = factory.createOptionalTypeNode(type.type);
3488                setTextRange(node, type);
3489                (node as Mutable<Node>).flags = type.flags;
3490                return node;
3491            }
3492            return type;
3493        }
3494
3495        function isNextTokenColonOrQuestionColon() {
3496            return nextToken() === SyntaxKind.ColonToken || (token() === SyntaxKind.QuestionToken && nextToken() === SyntaxKind.ColonToken);
3497        }
3498
3499        function isTupleElementName() {
3500            if (token() === SyntaxKind.DotDotDotToken) {
3501                return tokenIsIdentifierOrKeyword(nextToken()) && isNextTokenColonOrQuestionColon();
3502            }
3503            return tokenIsIdentifierOrKeyword(token()) && isNextTokenColonOrQuestionColon();
3504        }
3505
3506        function parseTupleElementNameOrTupleElementType() {
3507            if (lookAhead(isTupleElementName)) {
3508                const pos = getNodePos();
3509                const hasJSDoc = hasPrecedingJSDocComment();
3510                const dotDotDotToken = parseOptionalToken(SyntaxKind.DotDotDotToken);
3511                const name = parseIdentifierName();
3512                const questionToken = parseOptionalToken(SyntaxKind.QuestionToken);
3513                parseExpected(SyntaxKind.ColonToken);
3514                const type = parseTupleElementType();
3515                const node = factory.createNamedTupleMember(dotDotDotToken, name, questionToken, type);
3516                return withJSDoc(finishNode(node, pos), hasJSDoc);
3517            }
3518            return parseTupleElementType();
3519        }
3520
3521        function parseTupleType(): TupleTypeNode {
3522            const pos = getNodePos();
3523            return finishNode(
3524                factory.createTupleTypeNode(
3525                    parseBracketedList(ParsingContext.TupleElementTypes, parseTupleElementNameOrTupleElementType, SyntaxKind.OpenBracketToken, SyntaxKind.CloseBracketToken)
3526                ),
3527                pos
3528            );
3529        }
3530
3531        function parseParenthesizedType(): TypeNode {
3532            const pos = getNodePos();
3533            parseExpected(SyntaxKind.OpenParenToken);
3534            const type = parseType();
3535            parseExpected(SyntaxKind.CloseParenToken);
3536            return finishNode(factory.createParenthesizedType(type), pos);
3537        }
3538
3539        function parseModifiersForConstructorType(): NodeArray<Modifier> | undefined {
3540            let modifiers: NodeArray<Modifier> | undefined;
3541            if (token() === SyntaxKind.AbstractKeyword) {
3542                const pos = getNodePos();
3543                nextToken();
3544                const modifier = finishNode(factory.createToken(SyntaxKind.AbstractKeyword), pos);
3545                modifiers = createNodeArray<Modifier>([modifier], pos);
3546            }
3547            return modifiers;
3548        }
3549
3550        function parseFunctionOrConstructorType(): TypeNode {
3551            const pos = getNodePos();
3552            const hasJSDoc = hasPrecedingJSDocComment();
3553            const modifiers = parseModifiersForConstructorType();
3554            const isConstructorType = parseOptional(SyntaxKind.NewKeyword);
3555            const typeParameters = parseTypeParameters();
3556            const parameters = parseParameters(SignatureFlags.Type);
3557            const type = parseReturnType(SyntaxKind.EqualsGreaterThanToken, /*isType*/ false);
3558            const node = isConstructorType
3559                ? factory.createConstructorTypeNode(modifiers, typeParameters, parameters, type)
3560                : factory.createFunctionTypeNode(typeParameters, parameters, type);
3561            if (!isConstructorType) (node as Mutable<Node>).modifiers = modifiers;
3562            return withJSDoc(finishNode(node, pos), hasJSDoc);
3563        }
3564
3565        function parseKeywordAndNoDot(): TypeNode | undefined {
3566            const node = parseTokenNode<TypeNode>();
3567            return token() === SyntaxKind.DotToken ? undefined : node;
3568        }
3569
3570        function parseLiteralTypeNode(negative?: boolean): LiteralTypeNode {
3571            const pos = getNodePos();
3572            if (negative) {
3573                nextToken();
3574            }
3575            let expression: BooleanLiteral | NullLiteral | LiteralExpression | PrefixUnaryExpression =
3576                token() === SyntaxKind.TrueKeyword || token() === SyntaxKind.FalseKeyword || token() === SyntaxKind.NullKeyword ?
3577                    parseTokenNode<BooleanLiteral | NullLiteral>() :
3578                    parseLiteralLikeNode(token()) as LiteralExpression;
3579            if (negative) {
3580                expression = finishNode(factory.createPrefixUnaryExpression(SyntaxKind.MinusToken, expression), pos);
3581            }
3582            return finishNode(factory.createLiteralTypeNode(expression), pos);
3583        }
3584
3585        function isStartOfTypeOfImportType() {
3586            nextToken();
3587            return token() === SyntaxKind.ImportKeyword;
3588        }
3589
3590        function parseImportType(): ImportTypeNode {
3591            sourceFlags |= NodeFlags.PossiblyContainsDynamicImport;
3592            const pos = getNodePos();
3593            const isTypeOf = parseOptional(SyntaxKind.TypeOfKeyword);
3594            parseExpected(SyntaxKind.ImportKeyword);
3595            parseExpected(SyntaxKind.OpenParenToken);
3596            const type = parseType();
3597            parseExpected(SyntaxKind.CloseParenToken);
3598            const qualifier = parseOptional(SyntaxKind.DotToken) ? parseEntityNameOfTypeReference() : undefined;
3599            const typeArguments = parseTypeArgumentsOfTypeReference();
3600            return finishNode(factory.createImportTypeNode(type, qualifier, typeArguments, isTypeOf), pos);
3601        }
3602
3603        function nextTokenIsNumericOrBigIntLiteral() {
3604            nextToken();
3605            return token() === SyntaxKind.NumericLiteral || token() === SyntaxKind.BigIntLiteral;
3606        }
3607
3608        function parseNonArrayType(): TypeNode {
3609            switch (token()) {
3610                case SyntaxKind.AnyKeyword:
3611                case SyntaxKind.UnknownKeyword:
3612                case SyntaxKind.StringKeyword:
3613                case SyntaxKind.NumberKeyword:
3614                case SyntaxKind.BigIntKeyword:
3615                case SyntaxKind.SymbolKeyword:
3616                case SyntaxKind.BooleanKeyword:
3617                case SyntaxKind.UndefinedKeyword:
3618                case SyntaxKind.NeverKeyword:
3619                case SyntaxKind.ObjectKeyword:
3620                    // If these are followed by a dot, then parse these out as a dotted type reference instead.
3621                    return tryParse(parseKeywordAndNoDot) || parseTypeReference();
3622                case SyntaxKind.AsteriskEqualsToken:
3623                    // If there is '*=', treat it as * followed by postfix =
3624                    scanner.reScanAsteriskEqualsToken();
3625                    // falls through
3626                case SyntaxKind.AsteriskToken:
3627                    return parseJSDocAllType();
3628                case SyntaxKind.QuestionQuestionToken:
3629                    // If there is '??', treat it as prefix-'?' in JSDoc type.
3630                    scanner.reScanQuestionToken();
3631                    // falls through
3632                case SyntaxKind.QuestionToken:
3633                    return parseJSDocUnknownOrNullableType();
3634                case SyntaxKind.FunctionKeyword:
3635                    return parseJSDocFunctionType();
3636                case SyntaxKind.ExclamationToken:
3637                    return parseJSDocNonNullableType();
3638                case SyntaxKind.NoSubstitutionTemplateLiteral:
3639                case SyntaxKind.StringLiteral:
3640                case SyntaxKind.NumericLiteral:
3641                case SyntaxKind.BigIntLiteral:
3642                case SyntaxKind.TrueKeyword:
3643                case SyntaxKind.FalseKeyword:
3644                case SyntaxKind.NullKeyword:
3645                    return parseLiteralTypeNode();
3646                case SyntaxKind.MinusToken:
3647                    return lookAhead(nextTokenIsNumericOrBigIntLiteral) ? parseLiteralTypeNode(/*negative*/ true) : parseTypeReference();
3648                case SyntaxKind.VoidKeyword:
3649                    return parseTokenNode<TypeNode>();
3650                case SyntaxKind.ThisKeyword: {
3651                    const thisKeyword = parseThisTypeNode();
3652                    if (token() === SyntaxKind.IsKeyword && !scanner.hasPrecedingLineBreak()) {
3653                        return parseThisTypePredicate(thisKeyword);
3654                    }
3655                    else {
3656                        return thisKeyword;
3657                    }
3658                }
3659                case SyntaxKind.TypeOfKeyword:
3660                    return lookAhead(isStartOfTypeOfImportType) ? parseImportType() : parseTypeQuery();
3661                case SyntaxKind.OpenBraceToken:
3662                    return lookAhead(isStartOfMappedType) ? parseMappedType() : parseTypeLiteral();
3663                case SyntaxKind.OpenBracketToken:
3664                    return parseTupleType();
3665                case SyntaxKind.OpenParenToken:
3666                    return parseParenthesizedType();
3667                case SyntaxKind.ImportKeyword:
3668                    return parseImportType();
3669                case SyntaxKind.AssertsKeyword:
3670                    return lookAhead(nextTokenIsIdentifierOrKeywordOnSameLine) ? parseAssertsTypePredicate() : parseTypeReference();
3671                case SyntaxKind.TemplateHead:
3672                    return parseTemplateType();
3673                default:
3674                    return parseTypeReference();
3675            }
3676        }
3677
3678        function isStartOfType(inStartOfParameter?: boolean): boolean {
3679            switch (token()) {
3680                case SyntaxKind.AnyKeyword:
3681                case SyntaxKind.UnknownKeyword:
3682                case SyntaxKind.StringKeyword:
3683                case SyntaxKind.NumberKeyword:
3684                case SyntaxKind.BigIntKeyword:
3685                case SyntaxKind.BooleanKeyword:
3686                case SyntaxKind.ReadonlyKeyword:
3687                case SyntaxKind.SymbolKeyword:
3688                case SyntaxKind.UniqueKeyword:
3689                case SyntaxKind.VoidKeyword:
3690                case SyntaxKind.UndefinedKeyword:
3691                case SyntaxKind.NullKeyword:
3692                case SyntaxKind.ThisKeyword:
3693                case SyntaxKind.TypeOfKeyword:
3694                case SyntaxKind.NeverKeyword:
3695                case SyntaxKind.OpenBraceToken:
3696                case SyntaxKind.OpenBracketToken:
3697                case SyntaxKind.LessThanToken:
3698                case SyntaxKind.BarToken:
3699                case SyntaxKind.AmpersandToken:
3700                case SyntaxKind.NewKeyword:
3701                case SyntaxKind.StringLiteral:
3702                case SyntaxKind.NumericLiteral:
3703                case SyntaxKind.BigIntLiteral:
3704                case SyntaxKind.TrueKeyword:
3705                case SyntaxKind.FalseKeyword:
3706                case SyntaxKind.ObjectKeyword:
3707                case SyntaxKind.AsteriskToken:
3708                case SyntaxKind.QuestionToken:
3709                case SyntaxKind.ExclamationToken:
3710                case SyntaxKind.DotDotDotToken:
3711                case SyntaxKind.InferKeyword:
3712                case SyntaxKind.ImportKeyword:
3713                case SyntaxKind.AssertsKeyword:
3714                case SyntaxKind.NoSubstitutionTemplateLiteral:
3715                case SyntaxKind.TemplateHead:
3716                    return true;
3717                case SyntaxKind.FunctionKeyword:
3718                    return !inStartOfParameter;
3719                case SyntaxKind.MinusToken:
3720                    return !inStartOfParameter && lookAhead(nextTokenIsNumericOrBigIntLiteral);
3721                case SyntaxKind.OpenParenToken:
3722                    // Only consider '(' the start of a type if followed by ')', '...', an identifier, a modifier,
3723                    // or something that starts a type. We don't want to consider things like '(1)' a type.
3724                    return !inStartOfParameter && lookAhead(isStartOfParenthesizedOrFunctionType);
3725                default:
3726                    return isIdentifier();
3727            }
3728        }
3729
3730        function isStartOfParenthesizedOrFunctionType() {
3731            nextToken();
3732            return token() === SyntaxKind.CloseParenToken || isStartOfParameter(/*isJSDocParameter*/ false) || isStartOfType();
3733        }
3734
3735        function parsePostfixTypeOrHigher(): TypeNode {
3736            const pos = getNodePos();
3737            let type = parseNonArrayType();
3738            while (!scanner.hasPrecedingLineBreak()) {
3739                switch (token()) {
3740                    case SyntaxKind.ExclamationToken:
3741                        nextToken();
3742                        type = finishNode(factory.createJSDocNonNullableType(type), pos);
3743                        break;
3744                    case SyntaxKind.QuestionToken:
3745                        // If next token is start of a type we have a conditional type
3746                        if (lookAhead(nextTokenIsStartOfType)) {
3747                            return type;
3748                        }
3749                        nextToken();
3750                        type = finishNode(factory.createJSDocNullableType(type), pos);
3751                        break;
3752                    case SyntaxKind.OpenBracketToken:
3753                        parseExpected(SyntaxKind.OpenBracketToken);
3754                        if (isStartOfType()) {
3755                            const indexType = parseType();
3756                            parseExpected(SyntaxKind.CloseBracketToken);
3757                            type = finishNode(factory.createIndexedAccessTypeNode(type, indexType), pos);
3758                        }
3759                        else {
3760                            parseExpected(SyntaxKind.CloseBracketToken);
3761                            type = finishNode(factory.createArrayTypeNode(type), pos);
3762                        }
3763                        break;
3764                    default:
3765                        return type;
3766                }
3767            }
3768            return type;
3769        }
3770
3771        function parseTypeOperator(operator: SyntaxKind.KeyOfKeyword | SyntaxKind.UniqueKeyword | SyntaxKind.ReadonlyKeyword) {
3772            const pos = getNodePos();
3773            parseExpected(operator);
3774            return finishNode(factory.createTypeOperatorNode(operator, parseTypeOperatorOrHigher()), pos);
3775        }
3776
3777        function parseTypeParameterOfInferType() {
3778            const pos = getNodePos();
3779            return finishNode(
3780                factory.createTypeParameterDeclaration(
3781                    parseIdentifier(),
3782                    /*constraint*/ undefined,
3783                    /*defaultType*/ undefined
3784                ),
3785                pos
3786            );
3787        }
3788
3789        function parseInferType(): InferTypeNode {
3790            const pos = getNodePos();
3791            parseExpected(SyntaxKind.InferKeyword);
3792            return finishNode(factory.createInferTypeNode(parseTypeParameterOfInferType()), pos);
3793        }
3794
3795        function parseTypeOperatorOrHigher(): TypeNode {
3796            const operator = token();
3797            switch (operator) {
3798                case SyntaxKind.KeyOfKeyword:
3799                case SyntaxKind.UniqueKeyword:
3800                case SyntaxKind.ReadonlyKeyword:
3801                    return parseTypeOperator(operator);
3802                case SyntaxKind.InferKeyword:
3803                    return parseInferType();
3804            }
3805            return parsePostfixTypeOrHigher();
3806        }
3807
3808        function parseFunctionOrConstructorTypeToError(
3809            isInUnionType: boolean
3810        ): TypeNode | undefined {
3811            // the function type and constructor type shorthand notation
3812            // are not allowed directly in unions and intersections, but we'll
3813            // try to parse them gracefully and issue a helpful message.
3814            if (isStartOfFunctionTypeOrConstructorType()) {
3815                const type = parseFunctionOrConstructorType();
3816                let diagnostic: DiagnosticMessage;
3817                if (isFunctionTypeNode(type)) {
3818                    diagnostic = isInUnionType
3819                        ? Diagnostics.Function_type_notation_must_be_parenthesized_when_used_in_a_union_type
3820                        : Diagnostics.Function_type_notation_must_be_parenthesized_when_used_in_an_intersection_type;
3821                }
3822                else {
3823                    diagnostic = isInUnionType
3824                        ? Diagnostics.Constructor_type_notation_must_be_parenthesized_when_used_in_a_union_type
3825                        : Diagnostics.Constructor_type_notation_must_be_parenthesized_when_used_in_an_intersection_type;
3826
3827                }
3828                parseErrorAtRange(type, diagnostic);
3829                return type;
3830            }
3831            return undefined;
3832        }
3833
3834        function parseUnionOrIntersectionType(
3835            operator: SyntaxKind.BarToken | SyntaxKind.AmpersandToken,
3836            parseConstituentType: () => TypeNode,
3837            createTypeNode: (types: NodeArray<TypeNode>) => UnionOrIntersectionTypeNode
3838        ): TypeNode {
3839            const pos = getNodePos();
3840            const isUnionType = operator === SyntaxKind.BarToken;
3841            const hasLeadingOperator = parseOptional(operator);
3842            let type = hasLeadingOperator && parseFunctionOrConstructorTypeToError(isUnionType)
3843                || parseConstituentType();
3844            if (token() === operator || hasLeadingOperator) {
3845                const types = [type];
3846                while (parseOptional(operator)) {
3847                    types.push(parseFunctionOrConstructorTypeToError(isUnionType) || parseConstituentType());
3848                }
3849                type = finishNode(createTypeNode(createNodeArray(types, pos)), pos);
3850            }
3851            return type;
3852        }
3853
3854        function parseIntersectionTypeOrHigher(): TypeNode {
3855            return parseUnionOrIntersectionType(SyntaxKind.AmpersandToken, parseTypeOperatorOrHigher, factory.createIntersectionTypeNode);
3856        }
3857
3858        function parseUnionTypeOrHigher(): TypeNode {
3859            return parseUnionOrIntersectionType(SyntaxKind.BarToken, parseIntersectionTypeOrHigher, factory.createUnionTypeNode);
3860        }
3861
3862        function nextTokenIsNewKeyword(): boolean {
3863            nextToken();
3864            return token() === SyntaxKind.NewKeyword;
3865        }
3866
3867        function isStartOfFunctionTypeOrConstructorType(): boolean {
3868            if (token() === SyntaxKind.LessThanToken) {
3869                return true;
3870            }
3871            if (token() === SyntaxKind.OpenParenToken && lookAhead(isUnambiguouslyStartOfFunctionType)) {
3872                return true;
3873            }
3874            return token() === SyntaxKind.NewKeyword ||
3875                token() === SyntaxKind.AbstractKeyword && lookAhead(nextTokenIsNewKeyword);
3876        }
3877
3878        function skipParameterStart(): boolean {
3879            if (isModifierKind(token())) {
3880                // Skip modifiers
3881                parseModifiers();
3882            }
3883            if (isIdentifier() || token() === SyntaxKind.ThisKeyword) {
3884                nextToken();
3885                return true;
3886            }
3887            if (token() === SyntaxKind.OpenBracketToken || token() === SyntaxKind.OpenBraceToken) {
3888                // Return true if we can parse an array or object binding pattern with no errors
3889                const previousErrorCount = parseDiagnostics.length;
3890                parseIdentifierOrPattern();
3891                return previousErrorCount === parseDiagnostics.length;
3892            }
3893            return false;
3894        }
3895
3896        function isUnambiguouslyStartOfFunctionType() {
3897            nextToken();
3898            if (token() === SyntaxKind.CloseParenToken || token() === SyntaxKind.DotDotDotToken) {
3899                // ( )
3900                // ( ...
3901                return true;
3902            }
3903            if (skipParameterStart()) {
3904                // We successfully skipped modifiers (if any) and an identifier or binding pattern,
3905                // now see if we have something that indicates a parameter declaration
3906                if (token() === SyntaxKind.ColonToken || token() === SyntaxKind.CommaToken ||
3907                    token() === SyntaxKind.QuestionToken || token() === SyntaxKind.EqualsToken) {
3908                    // ( xxx :
3909                    // ( xxx ,
3910                    // ( xxx ?
3911                    // ( xxx =
3912                    return true;
3913                }
3914                if (token() === SyntaxKind.CloseParenToken) {
3915                    nextToken();
3916                    if (token() === SyntaxKind.EqualsGreaterThanToken) {
3917                        // ( xxx ) =>
3918                        return true;
3919                    }
3920                }
3921            }
3922            return false;
3923        }
3924
3925        function parseTypeOrTypePredicate(): TypeNode {
3926            const pos = getNodePos();
3927            const typePredicateVariable = isIdentifier() && tryParse(parseTypePredicatePrefix);
3928            const type = parseType();
3929            if (typePredicateVariable) {
3930                return finishNode(factory.createTypePredicateNode(/*assertsModifier*/ undefined, typePredicateVariable, type), pos);
3931            }
3932            else {
3933                return type;
3934            }
3935        }
3936
3937        function parseTypePredicatePrefix() {
3938            const id = parseIdentifier();
3939            if (token() === SyntaxKind.IsKeyword && !scanner.hasPrecedingLineBreak()) {
3940                nextToken();
3941                return id;
3942            }
3943        }
3944
3945        function parseAssertsTypePredicate(): TypeNode {
3946            const pos = getNodePos();
3947            const assertsModifier = parseExpectedToken(SyntaxKind.AssertsKeyword);
3948            const parameterName = token() === SyntaxKind.ThisKeyword ? parseThisTypeNode() : parseIdentifier();
3949            const type = parseOptional(SyntaxKind.IsKeyword) ? parseType() : undefined;
3950            return finishNode(factory.createTypePredicateNode(assertsModifier, parameterName, type), pos);
3951        }
3952
3953        function parseType(): TypeNode {
3954            // The rules about 'yield' only apply to actual code/expression contexts.  They don't
3955            // apply to 'type' contexts.  So we disable these parameters here before moving on.
3956            return doOutsideOfContext(NodeFlags.TypeExcludesFlags, parseTypeWorker);
3957        }
3958
3959        function parseEtsType(pos: number, name: string): TypeNode {
3960            const contextFlagsToClear = NodeFlags.TypeExcludesFlags & contextFlags;
3961            if (contextFlagsToClear) {
3962                // clear the requested context flags
3963                setContextFlag(/*val*/ false, contextFlagsToClear);
3964                const result = parseEtsTypeReferenceWorker(pos, name);
3965                // restore the context flags we just cleared
3966                setContextFlag(/*val*/ true, contextFlagsToClear);
3967                return result;
3968            }
3969
3970            return parseEtsTypeReferenceWorker(pos, name);
3971        }
3972
3973        function parseTypeWorker(noConditionalTypes?: boolean): TypeNode {
3974            if (isStartOfFunctionTypeOrConstructorType()) {
3975                return parseFunctionOrConstructorType();
3976            }
3977            const pos = getNodePos();
3978            const type = parseUnionTypeOrHigher();
3979            if (!noConditionalTypes && !scanner.hasPrecedingLineBreak() && parseOptional(SyntaxKind.ExtendsKeyword)) {
3980                // The type following 'extends' is not permitted to be another conditional type
3981                const extendsType = parseTypeWorker(/*noConditionalTypes*/ true);
3982                parseExpected(SyntaxKind.QuestionToken);
3983                const trueType = parseTypeWorker();
3984                parseExpected(SyntaxKind.ColonToken);
3985                const falseType = parseTypeWorker();
3986                return finishNode(factory.createConditionalTypeNode(type, extendsType, trueType, falseType), pos);
3987            }
3988            return type;
3989        }
3990
3991        function parseEtsTypeReferenceWorker(pos: number, name: string): TypeNode {
3992            return finishVirtualNode(
3993                factory.createTypeReferenceNode(
3994                    finishVirtualNode(factory.createIdentifier(name), pos, pos)
3995                ),
3996                pos, pos
3997            );
3998        }
3999
4000        function parseTypeAnnotation(): TypeNode | undefined {
4001            return parseOptional(SyntaxKind.ColonToken) ? parseType() : undefined;
4002        }
4003
4004        // EXPRESSIONS
4005        function isStartOfLeftHandSideExpression(): boolean {
4006            switch (token()) {
4007                case SyntaxKind.ThisKeyword:
4008                case SyntaxKind.SuperKeyword:
4009                case SyntaxKind.NullKeyword:
4010                case SyntaxKind.TrueKeyword:
4011                case SyntaxKind.FalseKeyword:
4012                case SyntaxKind.NumericLiteral:
4013                case SyntaxKind.BigIntLiteral:
4014                case SyntaxKind.StringLiteral:
4015                case SyntaxKind.NoSubstitutionTemplateLiteral:
4016                case SyntaxKind.TemplateHead:
4017                case SyntaxKind.OpenParenToken:
4018                case SyntaxKind.OpenBracketToken:
4019                case SyntaxKind.OpenBraceToken:
4020                case SyntaxKind.FunctionKeyword:
4021                case SyntaxKind.ClassKeyword:
4022                case SyntaxKind.NewKeyword:
4023                case SyntaxKind.SlashToken:
4024                case SyntaxKind.SlashEqualsToken:
4025                case SyntaxKind.Identifier:
4026                    return true;
4027                case SyntaxKind.StructKeyword:
4028                    return inEtsContext();
4029                case SyntaxKind.ImportKeyword:
4030                    return lookAhead(nextTokenIsOpenParenOrLessThanOrDot);
4031                default:
4032                    return isIdentifier();
4033            }
4034        }
4035
4036        function isStartOfExpression(): boolean {
4037            if (isStartOfLeftHandSideExpression()) {
4038                return true;
4039            }
4040
4041            switch (token()) {
4042                case SyntaxKind.PlusToken:
4043                case SyntaxKind.MinusToken:
4044                case SyntaxKind.TildeToken:
4045                case SyntaxKind.ExclamationToken:
4046                case SyntaxKind.DeleteKeyword:
4047                case SyntaxKind.TypeOfKeyword:
4048                case SyntaxKind.VoidKeyword:
4049                case SyntaxKind.PlusPlusToken:
4050                case SyntaxKind.MinusMinusToken:
4051                case SyntaxKind.LessThanToken:
4052                case SyntaxKind.AwaitKeyword:
4053                case SyntaxKind.YieldKeyword:
4054                case SyntaxKind.PrivateIdentifier:
4055                    // Yield/await always starts an expression.  Either it is an identifier (in which case
4056                    // it is definitely an expression).  Or it's a keyword (either because we're in
4057                    // a generator or async function, or in strict mode (or both)) and it started a yield or await expression.
4058                    return true;
4059                case SyntaxKind.DotToken:
4060                    return isValidExtendOrStylesContext();
4061                default:
4062                    // Error tolerance.  If we see the start of some binary operator, we consider
4063                    // that the start of an expression.  That way we'll parse out a missing identifier,
4064                    // give a good message about an identifier being missing, and then consume the
4065                    // rest of the binary expression.
4066                    if (isBinaryOperator()) {
4067                        return true;
4068                    }
4069
4070                    return isIdentifier();
4071            }
4072        }
4073
4074        function isValidExtendOrStylesContext(): boolean {
4075            return (inEtsExtendComponentsContext() && !!extendEtsComponentDeclaration) ||
4076                (inEtsStylesComponentsContext() && !!stylesEtsComponentDeclaration);
4077        }
4078
4079        function isStartOfExpressionStatement(): boolean {
4080            // As per the grammar, none of '{' or 'function' or 'class' can start an expression statement.
4081            return token() !== SyntaxKind.OpenBraceToken &&
4082                token() !== SyntaxKind.FunctionKeyword &&
4083                token() !== SyntaxKind.ClassKeyword &&
4084                (!inEtsContext() || token() !== SyntaxKind.StructKeyword) &&
4085                token() !== SyntaxKind.AtToken &&
4086                isStartOfExpression();
4087        }
4088
4089        function parseExpression(): Expression {
4090            // Expression[in]:
4091            //      AssignmentExpression[in]
4092            //      Expression[in] , AssignmentExpression[in]
4093
4094            // clear the decorator context when parsing Expression, as it should be unambiguous when parsing a decorator
4095            const saveDecoratorContext = inDecoratorContext();
4096            if (saveDecoratorContext) {
4097                setDecoratorContext(/*val*/ false);
4098            }
4099
4100            const pos = getNodePos();
4101            let expr = parseAssignmentExpressionOrHigher();
4102            let operatorToken: BinaryOperatorToken;
4103            while ((operatorToken = parseOptionalToken(SyntaxKind.CommaToken))) {
4104                expr = makeBinaryExpression(expr, operatorToken, parseAssignmentExpressionOrHigher(), pos);
4105            }
4106
4107            if (saveDecoratorContext) {
4108                setDecoratorContext(/*val*/ true);
4109            }
4110            return expr;
4111        }
4112
4113        function parseInitializer(): Expression | undefined {
4114            return parseOptional(SyntaxKind.EqualsToken) ? parseAssignmentExpressionOrHigher() : undefined;
4115        }
4116
4117        function parseAssignmentExpressionOrHigher(): Expression {
4118            //  AssignmentExpression[in,yield]:
4119            //      1) ConditionalExpression[?in,?yield]
4120            //      2) LeftHandSideExpression = AssignmentExpression[?in,?yield]
4121            //      3) LeftHandSideExpression AssignmentOperator AssignmentExpression[?in,?yield]
4122            //      4) ArrowFunctionExpression[?in,?yield]
4123            //      5) AsyncArrowFunctionExpression[in,yield,await]
4124            //      6) [+Yield] YieldExpression[?In]
4125            //
4126            // Note: for ease of implementation we treat productions '2' and '3' as the same thing.
4127            // (i.e. they're both BinaryExpressions with an assignment operator in it).
4128
4129            // First, do the simple check if we have a YieldExpression (production '6').
4130            if (isYieldExpression()) {
4131                return parseYieldExpression();
4132            }
4133
4134            // Then, check if we have an arrow function (production '4' and '5') that starts with a parenthesized
4135            // parameter list or is an async arrow function.
4136            // AsyncArrowFunctionExpression:
4137            //      1) async[no LineTerminator here]AsyncArrowBindingIdentifier[?Yield][no LineTerminator here]=>AsyncConciseBody[?In]
4138            //      2) CoverCallExpressionAndAsyncArrowHead[?Yield, ?Await][no LineTerminator here]=>AsyncConciseBody[?In]
4139            // Production (1) of AsyncArrowFunctionExpression is parsed in "tryParseAsyncSimpleArrowFunctionExpression".
4140            // And production (2) is parsed in "tryParseParenthesizedArrowFunctionExpression".
4141            //
4142            // If we do successfully parse arrow-function, we must *not* recurse for productions 1, 2 or 3. An ArrowFunction is
4143            // not a LeftHandSideExpression, nor does it start a ConditionalExpression.  So we are done
4144            // with AssignmentExpression if we see one.
4145            const arrowExpression = tryParseParenthesizedArrowFunctionExpression() || tryParseAsyncSimpleArrowFunctionExpression();
4146            if (arrowExpression) {
4147                return arrowExpression;
4148            }
4149
4150            // Now try to see if we're in production '1', '2' or '3'.  A conditional expression can
4151            // start with a LogicalOrExpression, while the assignment productions can only start with
4152            // LeftHandSideExpressions.
4153            //
4154            // So, first, we try to just parse out a BinaryExpression.  If we get something that is a
4155            // LeftHandSide or higher, then we can try to parse out the assignment expression part.
4156            // Otherwise, we try to parse out the conditional expression bit.  We want to allow any
4157            // binary expression here, so we pass in the 'lowest' precedence here so that it matches
4158            // and consumes anything.
4159            const pos = getNodePos();
4160            const expr = parseBinaryExpressionOrHigher(OperatorPrecedence.Lowest);
4161
4162            // To avoid a look-ahead, we did not handle the case of an arrow function with a single un-parenthesized
4163            // parameter ('x => ...') above. We handle it here by checking if the parsed expression was a single
4164            // identifier and the current token is an arrow.
4165            if (expr.kind === SyntaxKind.Identifier && token() === SyntaxKind.EqualsGreaterThanToken) {
4166                return parseSimpleArrowFunctionExpression(pos, <Identifier>expr, /*asyncModifier*/ undefined);
4167            }
4168
4169            // Now see if we might be in cases '2' or '3'.
4170            // If the expression was a LHS expression, and we have an assignment operator, then
4171            // we're in '2' or '3'. Consume the assignment and return.
4172            //
4173            // Note: we call reScanGreaterToken so that we get an appropriately merged token
4174            // for cases like `> > =` becoming `>>=`
4175            if (isLeftHandSideExpression(expr) && isAssignmentOperator(reScanGreaterToken())) {
4176                return makeBinaryExpression(expr, parseTokenNode(), parseAssignmentExpressionOrHigher(), pos);
4177            }
4178            // It's a CallExpression with open brace followed, therefore, we think it's an EtsComponentExpression
4179            if (inEtsContext() && isCallExpression(expr) && token() === SyntaxKind.OpenBraceToken) {
4180                return makeEtsComponentExpression(expr, pos);
4181            }
4182
4183            // It wasn't an assignment or a lambda.  This is a conditional expression:
4184            return parseConditionalExpressionRest(expr, pos);
4185        }
4186
4187        function makeEtsComponentExpression(expression: Expression, pos: number): EtsComponentExpression {
4188            const name = (<CallExpression>expression).expression;
4189            const body = parseFunctionBlock(SignatureFlags.None);
4190            return finishNode(factory.createEtsComponentExpression(<Identifier>name, (<CallExpression>expression).arguments, body), pos);
4191        }
4192
4193        function isYieldExpression(): boolean {
4194            if (token() === SyntaxKind.YieldKeyword) {
4195                // If we have a 'yield' keyword, and this is a context where yield expressions are
4196                // allowed, then definitely parse out a yield expression.
4197                if (inYieldContext()) {
4198                    return true;
4199                }
4200
4201                // We're in a context where 'yield expr' is not allowed.  However, if we can
4202                // definitely tell that the user was trying to parse a 'yield expr' and not
4203                // just a normal expr that start with a 'yield' identifier, then parse out
4204                // a 'yield expr'.  We can then report an error later that they are only
4205                // allowed in generator expressions.
4206                //
4207                // for example, if we see 'yield(foo)', then we'll have to treat that as an
4208                // invocation expression of something called 'yield'.  However, if we have
4209                // 'yield foo' then that is not legal as a normal expression, so we can
4210                // definitely recognize this as a yield expression.
4211                //
4212                // for now we just check if the next token is an identifier.  More heuristics
4213                // can be added here later as necessary.  We just need to make sure that we
4214                // don't accidentally consume something legal.
4215                return lookAhead(nextTokenIsIdentifierOrKeywordOrLiteralOnSameLine);
4216            }
4217
4218            return false;
4219        }
4220
4221        function nextTokenIsIdentifierOnSameLine() {
4222            nextToken();
4223            return !scanner.hasPrecedingLineBreak() && isIdentifier();
4224        }
4225
4226        function parseYieldExpression(): YieldExpression {
4227            const pos = getNodePos();
4228
4229            // YieldExpression[In] :
4230            //      yield
4231            //      yield [no LineTerminator here] [Lexical goal InputElementRegExp]AssignmentExpression[?In, Yield]
4232            //      yield [no LineTerminator here] * [Lexical goal InputElementRegExp]AssignmentExpression[?In, Yield]
4233            nextToken();
4234
4235            if (!scanner.hasPrecedingLineBreak() &&
4236                (token() === SyntaxKind.AsteriskToken || isStartOfExpression())) {
4237                return finishNode(
4238                    factory.createYieldExpression(
4239                        parseOptionalToken(SyntaxKind.AsteriskToken),
4240                        parseAssignmentExpressionOrHigher()
4241                    ),
4242                    pos
4243                );
4244            }
4245            else {
4246                // if the next token is not on the same line as yield.  or we don't have an '*' or
4247                // the start of an expression, then this is just a simple "yield" expression.
4248                return finishNode(factory.createYieldExpression(/*asteriskToken*/ undefined, /*expression*/ undefined), pos);
4249            }
4250        }
4251
4252        function parseSimpleArrowFunctionExpression(pos: number, identifier: Identifier, asyncModifier?: NodeArray<Modifier> | undefined): ArrowFunction {
4253            Debug.assert(token() === SyntaxKind.EqualsGreaterThanToken, "parseSimpleArrowFunctionExpression should only have been called if we had a =>");
4254            const parameter = factory.createParameterDeclaration(
4255                /*decorators*/ undefined,
4256                /*modifiers*/ undefined,
4257                /*dotDotDotToken*/ undefined,
4258                identifier,
4259                /*questionToken*/ undefined,
4260                /*type*/ undefined,
4261                /*initializer*/ undefined
4262            );
4263            finishNode(parameter, identifier.pos);
4264
4265            const parameters = createNodeArray<ParameterDeclaration>([parameter], parameter.pos, parameter.end);
4266            const equalsGreaterThanToken = parseExpectedToken(SyntaxKind.EqualsGreaterThanToken);
4267            const body = parseArrowFunctionExpressionBody(/*isAsync*/ !!asyncModifier);
4268            const node = factory.createArrowFunction(asyncModifier, /*typeParameters*/ undefined, parameters, /*type*/ undefined, equalsGreaterThanToken, body);
4269            return addJSDocComment(finishNode(node, pos));
4270        }
4271
4272        function tryParseParenthesizedArrowFunctionExpression(): Expression | undefined {
4273            const triState = isParenthesizedArrowFunctionExpression();
4274            if (triState === Tristate.False) {
4275                // It's definitely not a parenthesized arrow function expression.
4276                return undefined;
4277            }
4278
4279            // If we definitely have an arrow function, then we can just parse one, not requiring a
4280            // following => or { token. Otherwise, we *might* have an arrow function.  Try to parse
4281            // it out, but don't allow any ambiguity, and return 'undefined' if this could be an
4282            // expression instead.
4283            return triState === Tristate.True ?
4284                parseParenthesizedArrowFunctionExpression(/*allowAmbiguity*/ true) :
4285                tryParse(parsePossibleParenthesizedArrowFunctionExpression);
4286        }
4287
4288        //  True        -> We definitely expect a parenthesized arrow function here.
4289        //  False       -> There *cannot* be a parenthesized arrow function here.
4290        //  Unknown     -> There *might* be a parenthesized arrow function here.
4291        //                 Speculatively look ahead to be sure, and rollback if not.
4292        function isParenthesizedArrowFunctionExpression(): Tristate {
4293            if (token() === SyntaxKind.OpenParenToken || token() === SyntaxKind.LessThanToken || token() === SyntaxKind.AsyncKeyword) {
4294                return lookAhead(isParenthesizedArrowFunctionExpressionWorker);
4295            }
4296
4297            if (token() === SyntaxKind.EqualsGreaterThanToken) {
4298                // ERROR RECOVERY TWEAK:
4299                // If we see a standalone => try to parse it as an arrow function expression as that's
4300                // likely what the user intended to write.
4301                return Tristate.True;
4302            }
4303            // Definitely not a parenthesized arrow function.
4304            return Tristate.False;
4305        }
4306
4307        function isParenthesizedArrowFunctionExpressionWorker() {
4308            if (token() === SyntaxKind.AsyncKeyword) {
4309                nextToken();
4310                if (scanner.hasPrecedingLineBreak()) {
4311                    return Tristate.False;
4312                }
4313                if (token() !== SyntaxKind.OpenParenToken && token() !== SyntaxKind.LessThanToken) {
4314                    return Tristate.False;
4315                }
4316            }
4317
4318            const first = token();
4319            const second = nextToken();
4320
4321            if (first === SyntaxKind.OpenParenToken) {
4322                if (second === SyntaxKind.CloseParenToken) {
4323                    // Simple cases: "() =>", "(): ", and "() {".
4324                    // This is an arrow function with no parameters.
4325                    // The last one is not actually an arrow function,
4326                    // but this is probably what the user intended.
4327                    const third = nextToken();
4328                    switch (third) {
4329                        case SyntaxKind.EqualsGreaterThanToken:
4330                        case SyntaxKind.ColonToken:
4331                        case SyntaxKind.OpenBraceToken:
4332                            return Tristate.True;
4333                        default:
4334                            return Tristate.False;
4335                    }
4336                }
4337
4338                // If encounter "([" or "({", this could be the start of a binding pattern.
4339                // Examples:
4340                //      ([ x ]) => { }
4341                //      ({ x }) => { }
4342                //      ([ x ])
4343                //      ({ x })
4344                if (second === SyntaxKind.OpenBracketToken || second === SyntaxKind.OpenBraceToken) {
4345                    return Tristate.Unknown;
4346                }
4347
4348                // Simple case: "(..."
4349                // This is an arrow function with a rest parameter.
4350                if (second === SyntaxKind.DotDotDotToken) {
4351                    return Tristate.True;
4352                }
4353
4354                // Check for "(xxx yyy", where xxx is a modifier and yyy is an identifier. This
4355                // isn't actually allowed, but we want to treat it as a lambda so we can provide
4356                // a good error message.
4357                if (isModifierKind(second) && second !== SyntaxKind.AsyncKeyword && lookAhead(nextTokenIsIdentifier)) {
4358                    return Tristate.True;
4359                }
4360
4361                // If we had "(" followed by something that's not an identifier,
4362                // then this definitely doesn't look like a lambda.  "this" is not
4363                // valid, but we want to parse it and then give a semantic error.
4364                if (!isIdentifier() && second !== SyntaxKind.ThisKeyword) {
4365                    return Tristate.False;
4366                }
4367
4368                switch (nextToken()) {
4369                    case SyntaxKind.ColonToken:
4370                        // If we have something like "(a:", then we must have a
4371                        // type-annotated parameter in an arrow function expression.
4372                        return Tristate.True;
4373                    case SyntaxKind.QuestionToken:
4374                        nextToken();
4375                        // If we have "(a?:" or "(a?," or "(a?=" or "(a?)" then it is definitely a lambda.
4376                        if (token() === SyntaxKind.ColonToken || token() === SyntaxKind.CommaToken || token() === SyntaxKind.EqualsToken || token() === SyntaxKind.CloseParenToken) {
4377                            return Tristate.True;
4378                        }
4379                        // Otherwise it is definitely not a lambda.
4380                        return Tristate.False;
4381                    case SyntaxKind.CommaToken:
4382                    case SyntaxKind.EqualsToken:
4383                    case SyntaxKind.CloseParenToken:
4384                        // If we have "(a," or "(a=" or "(a)" this *could* be an arrow function
4385                        return Tristate.Unknown;
4386                }
4387                // It is definitely not an arrow function
4388                return Tristate.False;
4389            }
4390            else {
4391                Debug.assert(first === SyntaxKind.LessThanToken);
4392
4393                // If we have "<" not followed by an identifier,
4394                // then this definitely is not an arrow function.
4395                if (!isIdentifier()) {
4396                    return Tristate.False;
4397                }
4398
4399                // JSX overrides
4400                if (languageVariant === LanguageVariant.JSX) {
4401                    const isArrowFunctionInJsx = lookAhead(() => {
4402                        const third = nextToken();
4403                        if (third === SyntaxKind.ExtendsKeyword) {
4404                            const fourth = nextToken();
4405                            switch (fourth) {
4406                                case SyntaxKind.EqualsToken:
4407                                case SyntaxKind.GreaterThanToken:
4408                                    return false;
4409                                default:
4410                                    return true;
4411                            }
4412                        }
4413                        else if (third === SyntaxKind.CommaToken) {
4414                            return true;
4415                        }
4416                        return false;
4417                    });
4418
4419                    if (isArrowFunctionInJsx) {
4420                        return Tristate.True;
4421                    }
4422
4423                    return Tristate.False;
4424                }
4425
4426                // This *could* be a parenthesized arrow function.
4427                return Tristate.Unknown;
4428            }
4429        }
4430
4431        function parsePossibleParenthesizedArrowFunctionExpression(): ArrowFunction | undefined {
4432            const tokenPos = scanner.getTokenPos();
4433            if (notParenthesizedArrow?.has(tokenPos)) {
4434                return undefined;
4435            }
4436
4437            const result = parseParenthesizedArrowFunctionExpression(/*allowAmbiguity*/ false);
4438            if (!result) {
4439                (notParenthesizedArrow || (notParenthesizedArrow = new Set())).add(tokenPos);
4440            }
4441
4442            return result;
4443        }
4444
4445        function tryParseAsyncSimpleArrowFunctionExpression(): ArrowFunction | undefined {
4446            // We do a check here so that we won't be doing unnecessarily call to "lookAhead"
4447            if (token() === SyntaxKind.AsyncKeyword) {
4448                if (lookAhead(isUnParenthesizedAsyncArrowFunctionWorker) === Tristate.True) {
4449                    const pos = getNodePos();
4450                    const asyncModifier = parseModifiersForArrowFunction();
4451                    const expr = parseBinaryExpressionOrHigher(OperatorPrecedence.Lowest);
4452                    return parseSimpleArrowFunctionExpression(pos, <Identifier>expr, asyncModifier);
4453                }
4454            }
4455            return undefined;
4456        }
4457
4458        function isUnParenthesizedAsyncArrowFunctionWorker(): Tristate {
4459            // AsyncArrowFunctionExpression:
4460            //      1) async[no LineTerminator here]AsyncArrowBindingIdentifier[?Yield][no LineTerminator here]=>AsyncConciseBody[?In]
4461            //      2) CoverCallExpressionAndAsyncArrowHead[?Yield, ?Await][no LineTerminator here]=>AsyncConciseBody[?In]
4462            if (token() === SyntaxKind.AsyncKeyword) {
4463                nextToken();
4464                // If the "async" is followed by "=>" token then it is not a beginning of an async arrow-function
4465                // but instead a simple arrow-function which will be parsed inside "parseAssignmentExpressionOrHigher"
4466                if (scanner.hasPrecedingLineBreak() || token() === SyntaxKind.EqualsGreaterThanToken) {
4467                    return Tristate.False;
4468                }
4469                // Check for un-parenthesized AsyncArrowFunction
4470                const expr = parseBinaryExpressionOrHigher(OperatorPrecedence.Lowest);
4471                if (!scanner.hasPrecedingLineBreak() && expr.kind === SyntaxKind.Identifier && token() === SyntaxKind.EqualsGreaterThanToken) {
4472                    return Tristate.True;
4473                }
4474            }
4475
4476            return Tristate.False;
4477        }
4478
4479        function parseParenthesizedArrowFunctionExpression(allowAmbiguity: boolean): ArrowFunction | undefined {
4480            const pos = getNodePos();
4481            const hasJSDoc = hasPrecedingJSDocComment();
4482            const modifiers = parseModifiersForArrowFunction();
4483            const isAsync = some(modifiers, isAsyncModifier) ? SignatureFlags.Await : SignatureFlags.None;
4484            // Arrow functions are never generators.
4485            //
4486            // If we're speculatively parsing a signature for a parenthesized arrow function, then
4487            // we have to have a complete parameter list.  Otherwise we might see something like
4488            // a => (b => c)
4489            // And think that "(b =>" was actually a parenthesized arrow function with a missing
4490            // close paren.
4491            const typeParameters = parseTypeParameters();
4492
4493            let parameters: NodeArray<ParameterDeclaration>;
4494            if (!parseExpected(SyntaxKind.OpenParenToken)) {
4495                if (!allowAmbiguity) {
4496                    return undefined;
4497                }
4498                parameters = createMissingList<ParameterDeclaration>();
4499            }
4500            else {
4501                parameters = parseParametersWorker(isAsync);
4502                if (!parseExpected(SyntaxKind.CloseParenToken) && !allowAmbiguity) {
4503                    return undefined;
4504                }
4505            }
4506
4507            const type = parseReturnType(SyntaxKind.ColonToken, /*isType*/ false);
4508            if (type && !allowAmbiguity && typeHasArrowFunctionBlockingParseError(type)) {
4509                return undefined;
4510            }
4511
4512            // Parsing a signature isn't enough.
4513            // Parenthesized arrow signatures often look like other valid expressions.
4514            // For instance:
4515            //  - "(x = 10)" is an assignment expression parsed as a signature with a default parameter value.
4516            //  - "(x,y)" is a comma expression parsed as a signature with two parameters.
4517            //  - "a ? (b): c" will have "(b):" parsed as a signature with a return type annotation.
4518            //  - "a ? (b): function() {}" will too, since function() is a valid JSDoc function type.
4519            //
4520            // So we need just a bit of lookahead to ensure that it can only be a signature.
4521            const hasJSDocFunctionType = type && isJSDocFunctionType(type);
4522            if (!allowAmbiguity && token() !== SyntaxKind.EqualsGreaterThanToken && (hasJSDocFunctionType || token() !== SyntaxKind.OpenBraceToken)) {
4523                // Returning undefined here will cause our caller to rewind to where we started from.
4524                    return undefined;
4525            }
4526
4527            // If we have an arrow, then try to parse the body. Even if not, try to parse if we
4528            // have an opening brace, just in case we're in an error state.
4529            const lastToken = token();
4530            const equalsGreaterThanToken = parseExpectedToken(SyntaxKind.EqualsGreaterThanToken);
4531            const body = (lastToken === SyntaxKind.EqualsGreaterThanToken || lastToken === SyntaxKind.OpenBraceToken)
4532                ? parseArrowFunctionExpressionBody(some(modifiers, isAsyncModifier))
4533                : parseIdentifier();
4534
4535            const node = factory.createArrowFunction(modifiers, typeParameters, parameters, type, equalsGreaterThanToken, body);
4536            return withJSDoc(finishNode(node, pos), hasJSDoc);
4537        }
4538
4539        function parseArrowFunctionExpressionBody(isAsync: boolean): Block | Expression {
4540            if (token() === SyntaxKind.OpenBraceToken) {
4541                return parseFunctionBlock(isAsync ? SignatureFlags.Await : SignatureFlags.None);
4542            }
4543
4544            if (token() !== SyntaxKind.SemicolonToken &&
4545                token() !== SyntaxKind.FunctionKeyword &&
4546                token() !== SyntaxKind.ClassKeyword &&
4547                (!inEtsContext() || token() !== SyntaxKind.StructKeyword) &&
4548                isStartOfStatement() &&
4549                !isStartOfExpressionStatement()) {
4550                // Check if we got a plain statement (i.e. no expression-statements, no function/class expressions/declarations)
4551                //
4552                // Here we try to recover from a potential error situation in the case where the
4553                // user meant to supply a block. For example, if the user wrote:
4554                //
4555                //  a =>
4556                //      let v = 0;
4557                //  }
4558                //
4559                // they may be missing an open brace.  Check to see if that's the case so we can
4560                // try to recover better.  If we don't do this, then the next close curly we see may end
4561                // up preemptively closing the containing construct.
4562                //
4563                // Note: even when 'IgnoreMissingOpenBrace' is passed, parseBody will still error.
4564                return parseFunctionBlock(SignatureFlags.IgnoreMissingOpenBrace | (isAsync ? SignatureFlags.Await : SignatureFlags.None));
4565            }
4566
4567            const savedTopLevel = topLevel;
4568            topLevel = false;
4569            const node = isAsync
4570                ? doInAwaitContext(parseAssignmentExpressionOrHigher)
4571                : doOutsideOfAwaitContext(parseAssignmentExpressionOrHigher);
4572            topLevel = savedTopLevel;
4573            return node;
4574        }
4575
4576        function parseConditionalExpressionRest(leftOperand: Expression, pos: number): Expression {
4577            // Note: we are passed in an expression which was produced from parseBinaryExpressionOrHigher.
4578            const questionToken = parseOptionalToken(SyntaxKind.QuestionToken);
4579            if (!questionToken) {
4580                return leftOperand;
4581            }
4582
4583            // Note: we explicitly 'allowIn' in the whenTrue part of the condition expression, and
4584            // we do not that for the 'whenFalse' part.
4585            let colonToken;
4586            return finishNode(
4587                factory.createConditionalExpression(
4588                    leftOperand,
4589                    questionToken,
4590                    doOutsideOfContext(disallowInAndDecoratorContext, parseAssignmentExpressionOrHigher),
4591                    colonToken = parseExpectedToken(SyntaxKind.ColonToken),
4592                    nodeIsPresent(colonToken)
4593                        ? parseAssignmentExpressionOrHigher()
4594                        : createMissingNode(SyntaxKind.Identifier, /*reportAtCurrentPosition*/ false, Diagnostics._0_expected, tokenToString(SyntaxKind.ColonToken))
4595                ),
4596                pos
4597            );
4598        }
4599
4600        function parseBinaryExpressionOrHigher(precedence: OperatorPrecedence): Expression {
4601            const pos = getNodePos();
4602            const leftOperand = parseUnaryExpressionOrHigher();
4603            return parseBinaryExpressionRest(precedence, leftOperand, pos);
4604        }
4605
4606        function isInOrOfKeyword(t: SyntaxKind) {
4607            return t === SyntaxKind.InKeyword || t === SyntaxKind.OfKeyword;
4608        }
4609
4610        function parseBinaryExpressionRest(precedence: OperatorPrecedence, leftOperand: Expression, pos: number): Expression {
4611            while (true) {
4612                // We either have a binary operator here, or we're finished.  We call
4613                // reScanGreaterToken so that we merge token sequences like > and = into >=
4614
4615                reScanGreaterToken();
4616                const newPrecedence = getBinaryOperatorPrecedence(token());
4617
4618                // Check the precedence to see if we should "take" this operator
4619                // - For left associative operator (all operator but **), consume the operator,
4620                //   recursively call the function below, and parse binaryExpression as a rightOperand
4621                //   of the caller if the new precedence of the operator is greater then or equal to the current precedence.
4622                //   For example:
4623                //      a - b - c;
4624                //            ^token; leftOperand = b. Return b to the caller as a rightOperand
4625                //      a * b - c
4626                //            ^token; leftOperand = b. Return b to the caller as a rightOperand
4627                //      a - b * c;
4628                //            ^token; leftOperand = b. Return b * c to the caller as a rightOperand
4629                // - For right associative operator (**), consume the operator, recursively call the function
4630                //   and parse binaryExpression as a rightOperand of the caller if the new precedence of
4631                //   the operator is strictly grater than the current precedence
4632                //   For example:
4633                //      a ** b ** c;
4634                //             ^^token; leftOperand = b. Return b ** c to the caller as a rightOperand
4635                //      a - b ** c;
4636                //            ^^token; leftOperand = b. Return b ** c to the caller as a rightOperand
4637                //      a ** b - c
4638                //             ^token; leftOperand = b. Return b to the caller as a rightOperand
4639                const consumeCurrentOperator = token() === SyntaxKind.AsteriskAsteriskToken ?
4640                    newPrecedence >= precedence :
4641                    newPrecedence > precedence;
4642
4643                if (!consumeCurrentOperator) {
4644                    break;
4645                }
4646
4647                if (token() === SyntaxKind.InKeyword && inDisallowInContext()) {
4648                    break;
4649                }
4650
4651                if (token() === SyntaxKind.AsKeyword) {
4652                    // Make sure we *do* perform ASI for constructs like this:
4653                    //    var x = foo
4654                    //    as (Bar)
4655                    // This should be parsed as an initialized variable, followed
4656                    // by a function call to 'as' with the argument 'Bar'
4657                    if (scanner.hasPrecedingLineBreak()) {
4658                        break;
4659                    }
4660                    else {
4661                        nextToken();
4662                        leftOperand = makeAsExpression(leftOperand, parseType());
4663                    }
4664                }
4665                else {
4666                    leftOperand = makeBinaryExpression(leftOperand, parseTokenNode(), parseBinaryExpressionOrHigher(newPrecedence), pos);
4667                }
4668            }
4669
4670            return leftOperand;
4671        }
4672
4673        function isBinaryOperator() {
4674            if (inDisallowInContext() && token() === SyntaxKind.InKeyword) {
4675                return false;
4676            }
4677
4678            return getBinaryOperatorPrecedence(token()) > 0;
4679        }
4680
4681        function makeBinaryExpression(left: Expression, operatorToken: BinaryOperatorToken, right: Expression, pos: number): BinaryExpression {
4682            return finishNode(factory.createBinaryExpression(left, operatorToken, right), pos);
4683        }
4684
4685        function makeAsExpression(left: Expression, right: TypeNode): AsExpression {
4686            return finishNode(factory.createAsExpression(left, right), left.pos);
4687        }
4688
4689        function parsePrefixUnaryExpression() {
4690            const pos = getNodePos();
4691            return finishNode(factory.createPrefixUnaryExpression(<PrefixUnaryOperator>token(), nextTokenAnd(parseSimpleUnaryExpression)), pos);
4692        }
4693
4694        function parseDeleteExpression() {
4695            const pos = getNodePos();
4696            return finishNode(factory.createDeleteExpression(nextTokenAnd(parseSimpleUnaryExpression)), pos);
4697        }
4698
4699        function parseTypeOfExpression() {
4700            const pos = getNodePos();
4701            return finishNode(factory.createTypeOfExpression(nextTokenAnd(parseSimpleUnaryExpression)), pos);
4702        }
4703
4704        function parseVoidExpression() {
4705            const pos = getNodePos();
4706            return finishNode(factory.createVoidExpression(nextTokenAnd(parseSimpleUnaryExpression)), pos);
4707        }
4708
4709        function isAwaitExpression(): boolean {
4710            if (token() === SyntaxKind.AwaitKeyword) {
4711                if (inAwaitContext()) {
4712                    return true;
4713                }
4714
4715                // here we are using similar heuristics as 'isYieldExpression'
4716                return lookAhead(nextTokenIsIdentifierOrKeywordOrLiteralOnSameLine);
4717            }
4718
4719            return false;
4720        }
4721
4722        function parseAwaitExpression() {
4723            const pos = getNodePos();
4724            return finishNode(factory.createAwaitExpression(nextTokenAnd(parseSimpleUnaryExpression)), pos);
4725        }
4726
4727        /**
4728         * Parse ES7 exponential expression and await expression
4729         *
4730         * ES7 ExponentiationExpression:
4731         *      1) UnaryExpression[?Yield]
4732         *      2) UpdateExpression[?Yield] ** ExponentiationExpression[?Yield]
4733         *
4734         */
4735        function parseUnaryExpressionOrHigher(): UnaryExpression | BinaryExpression {
4736            /**
4737             * ES7 UpdateExpression:
4738             *      1) LeftHandSideExpression[?Yield]
4739             *      2) LeftHandSideExpression[?Yield][no LineTerminator here]++
4740             *      3) LeftHandSideExpression[?Yield][no LineTerminator here]--
4741             *      4) ++UnaryExpression[?Yield]
4742             *      5) --UnaryExpression[?Yield]
4743             */
4744            if (isUpdateExpression()) {
4745                const pos = getNodePos();
4746                const updateExpression = parseUpdateExpression();
4747                return token() === SyntaxKind.AsteriskAsteriskToken ?
4748                    <BinaryExpression>parseBinaryExpressionRest(getBinaryOperatorPrecedence(token()), updateExpression, pos) :
4749                    updateExpression;
4750            }
4751
4752            /**
4753             * ES7 UnaryExpression:
4754             *      1) UpdateExpression[?yield]
4755             *      2) delete UpdateExpression[?yield]
4756             *      3) void UpdateExpression[?yield]
4757             *      4) typeof UpdateExpression[?yield]
4758             *      5) + UpdateExpression[?yield]
4759             *      6) - UpdateExpression[?yield]
4760             *      7) ~ UpdateExpression[?yield]
4761             *      8) ! UpdateExpression[?yield]
4762             */
4763            const unaryOperator = token();
4764            const simpleUnaryExpression = parseSimpleUnaryExpression();
4765            if (token() === SyntaxKind.AsteriskAsteriskToken) {
4766                const pos = skipTrivia(sourceText, simpleUnaryExpression.pos);
4767                const { end } = simpleUnaryExpression;
4768                if (simpleUnaryExpression.kind === SyntaxKind.TypeAssertionExpression) {
4769                    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);
4770                }
4771                else {
4772                    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));
4773                }
4774            }
4775            return simpleUnaryExpression;
4776        }
4777
4778        /**
4779         * Parse ES7 simple-unary expression or higher:
4780         *
4781         * ES7 UnaryExpression:
4782         *      1) UpdateExpression[?yield]
4783         *      2) delete UnaryExpression[?yield]
4784         *      3) void UnaryExpression[?yield]
4785         *      4) typeof UnaryExpression[?yield]
4786         *      5) + UnaryExpression[?yield]
4787         *      6) - UnaryExpression[?yield]
4788         *      7) ~ UnaryExpression[?yield]
4789         *      8) ! UnaryExpression[?yield]
4790         *      9) [+Await] await UnaryExpression[?yield]
4791         */
4792        function parseSimpleUnaryExpression(): UnaryExpression {
4793            switch (token()) {
4794                case SyntaxKind.PlusToken:
4795                case SyntaxKind.MinusToken:
4796                case SyntaxKind.TildeToken:
4797                case SyntaxKind.ExclamationToken:
4798                    return parsePrefixUnaryExpression();
4799                case SyntaxKind.DeleteKeyword:
4800                    return parseDeleteExpression();
4801                case SyntaxKind.TypeOfKeyword:
4802                    return parseTypeOfExpression();
4803                case SyntaxKind.VoidKeyword:
4804                    return parseVoidExpression();
4805                case SyntaxKind.LessThanToken:
4806                    // This is modified UnaryExpression grammar in TypeScript
4807                    //  UnaryExpression (modified):
4808                    //      < type > UnaryExpression
4809                    return parseTypeAssertion();
4810                case SyntaxKind.AwaitKeyword:
4811                    if (isAwaitExpression()) {
4812                        return parseAwaitExpression();
4813                    }
4814                    // falls through
4815                default:
4816                    return parseUpdateExpression();
4817            }
4818        }
4819
4820        /**
4821         * Check if the current token can possibly be an ES7 increment expression.
4822         *
4823         * ES7 UpdateExpression:
4824         *      LeftHandSideExpression[?Yield]
4825         *      LeftHandSideExpression[?Yield][no LineTerminator here]++
4826         *      LeftHandSideExpression[?Yield][no LineTerminator here]--
4827         *      ++LeftHandSideExpression[?Yield]
4828         *      --LeftHandSideExpression[?Yield]
4829         */
4830        function isUpdateExpression(): boolean {
4831            // This function is called inside parseUnaryExpression to decide
4832            // whether to call parseSimpleUnaryExpression or call parseUpdateExpression directly
4833            switch (token()) {
4834                case SyntaxKind.PlusToken:
4835                case SyntaxKind.MinusToken:
4836                case SyntaxKind.TildeToken:
4837                case SyntaxKind.ExclamationToken:
4838                case SyntaxKind.DeleteKeyword:
4839                case SyntaxKind.TypeOfKeyword:
4840                case SyntaxKind.VoidKeyword:
4841                case SyntaxKind.AwaitKeyword:
4842                    return false;
4843                case SyntaxKind.LessThanToken:
4844                    // If we are not in JSX context, we are parsing TypeAssertion which is an UnaryExpression
4845                    if (languageVariant !== LanguageVariant.JSX) {
4846                        return false;
4847                    }
4848                    // We are in JSX context and the token is part of JSXElement.
4849                    // falls through
4850                default:
4851                    return true;
4852            }
4853        }
4854
4855        /**
4856         * Parse ES7 UpdateExpression. UpdateExpression is used instead of ES6's PostFixExpression.
4857         *
4858         * ES7 UpdateExpression[yield]:
4859         *      1) LeftHandSideExpression[?yield]
4860         *      2) LeftHandSideExpression[?yield] [[no LineTerminator here]]++
4861         *      3) LeftHandSideExpression[?yield] [[no LineTerminator here]]--
4862         *      4) ++LeftHandSideExpression[?yield]
4863         *      5) --LeftHandSideExpression[?yield]
4864         * In TypeScript (2), (3) are parsed as PostfixUnaryExpression. (4), (5) are parsed as PrefixUnaryExpression
4865         */
4866        function parseUpdateExpression(): UpdateExpression {
4867            if (token() === SyntaxKind.PlusPlusToken || token() === SyntaxKind.MinusMinusToken) {
4868                const pos = getNodePos();
4869                return finishNode(factory.createPrefixUnaryExpression(<PrefixUnaryOperator>token(), nextTokenAnd(parseLeftHandSideExpressionOrHigher)), pos);
4870            }
4871            else if (languageVariant === LanguageVariant.JSX && token() === SyntaxKind.LessThanToken && lookAhead(nextTokenIsIdentifierOrKeywordOrGreaterThan)) {
4872                // JSXElement is part of primaryExpression
4873                return parseJsxElementOrSelfClosingElementOrFragment(/*inExpressionContext*/ true);
4874            }
4875
4876            const expression = parseLeftHandSideExpressionOrHigher();
4877
4878            Debug.assert(isLeftHandSideExpression(expression));
4879            if ((token() === SyntaxKind.PlusPlusToken || token() === SyntaxKind.MinusMinusToken) && !scanner.hasPrecedingLineBreak()) {
4880                const operator = <PostfixUnaryOperator>token();
4881                nextToken();
4882                return finishNode(factory.createPostfixUnaryExpression(expression, operator), expression.pos);
4883            }
4884
4885            return expression;
4886        }
4887
4888        function parseLeftHandSideExpressionOrHigher(): LeftHandSideExpression {
4889            // Original Ecma:
4890            // LeftHandSideExpression: See 11.2
4891            //      NewExpression
4892            //      CallExpression
4893            //
4894            // Our simplification:
4895            //
4896            // LeftHandSideExpression: See 11.2
4897            //      MemberExpression
4898            //      CallExpression
4899            //
4900            // See comment in parseMemberExpressionOrHigher on how we replaced NewExpression with
4901            // MemberExpression to make our lives easier.
4902            //
4903            // to best understand the below code, it's important to see how CallExpression expands
4904            // out into its own productions:
4905            //
4906            // CallExpression:
4907            //      MemberExpression Arguments
4908            //      CallExpression Arguments
4909            //      CallExpression[Expression]
4910            //      CallExpression.IdentifierName
4911            //      import (AssignmentExpression)
4912            //      super Arguments
4913            //      super.IdentifierName
4914            //
4915            // Because of the recursion in these calls, we need to bottom out first. There are three
4916            // bottom out states we can run into: 1) We see 'super' which must start either of
4917            // the last two CallExpression productions. 2) We see 'import' which must start import call.
4918            // 3)we have a MemberExpression which either completes the LeftHandSideExpression,
4919            // or starts the beginning of the first four CallExpression productions.
4920            const pos = getNodePos();
4921            let expression: MemberExpression;
4922            if (token() === SyntaxKind.ImportKeyword) {
4923                if (lookAhead(nextTokenIsOpenParenOrLessThan)) {
4924                    // We don't want to eagerly consume all import keyword as import call expression so we look ahead to find "("
4925                    // For example:
4926                    //      var foo3 = require("subfolder
4927                    //      import * as foo1 from "module-from-node
4928                    // We want this import to be a statement rather than import call expression
4929                    sourceFlags |= NodeFlags.PossiblyContainsDynamicImport;
4930                    expression = parseTokenNode<PrimaryExpression>();
4931                }
4932                else if (lookAhead(nextTokenIsDot)) {
4933                    // This is an 'import.*' metaproperty (i.e. 'import.meta')
4934                    nextToken(); // advance past the 'import'
4935                    nextToken(); // advance past the dot
4936                    expression = finishNode(factory.createMetaProperty(SyntaxKind.ImportKeyword, parseIdentifierName()), pos);
4937                    sourceFlags |= NodeFlags.PossiblyContainsImportMeta;
4938                }
4939                else {
4940                    expression = parseMemberExpressionOrHigher();
4941                }
4942            }
4943            else {
4944                expression = token() === SyntaxKind.SuperKeyword ? parseSuperExpression() : parseMemberExpressionOrHigher();
4945            }
4946
4947            // Now, we *may* be complete.  However, we might have consumed the start of a
4948            // CallExpression or OptionalExpression.  As such, we need to consume the rest
4949            // of it here to be complete.
4950            return parseCallExpressionRest(pos, expression);
4951        }
4952
4953        function parseMemberExpressionOrHigher(): MemberExpression {
4954            // Note: to make our lives simpler, we decompose the NewExpression productions and
4955            // place ObjectCreationExpression and FunctionExpression into PrimaryExpression.
4956            // like so:
4957            //
4958            //   PrimaryExpression : See 11.1
4959            //      this
4960            //      Identifier
4961            //      Literal
4962            //      ArrayLiteral
4963            //      ObjectLiteral
4964            //      (Expression)
4965            //      FunctionExpression
4966            //      new MemberExpression Arguments?
4967            //
4968            //   MemberExpression : See 11.2
4969            //      PrimaryExpression
4970            //      MemberExpression[Expression]
4971            //      MemberExpression.IdentifierName
4972            //
4973            //   CallExpression : See 11.2
4974            //      MemberExpression
4975            //      CallExpression Arguments
4976            //      CallExpression[Expression]
4977            //      CallExpression.IdentifierName
4978            //
4979            // Technically this is ambiguous.  i.e. CallExpression defines:
4980            //
4981            //   CallExpression:
4982            //      CallExpression Arguments
4983            //
4984            // If you see: "new Foo()"
4985            //
4986            // Then that could be treated as a single ObjectCreationExpression, or it could be
4987            // treated as the invocation of "new Foo".  We disambiguate that in code (to match
4988            // the original grammar) by making sure that if we see an ObjectCreationExpression
4989            // we always consume arguments if they are there. So we treat "new Foo()" as an
4990            // object creation only, and not at all as an invocation.  Another way to think
4991            // about this is that for every "new" that we see, we will consume an argument list if
4992            // it is there as part of the *associated* object creation node.  Any additional
4993            // argument lists we see, will become invocation expressions.
4994            //
4995            // Because there are no other places in the grammar now that refer to FunctionExpression
4996            // or ObjectCreationExpression, it is safe to push down into the PrimaryExpression
4997            // production.
4998            //
4999            // Because CallExpression and MemberExpression are left recursive, we need to bottom out
5000            // of the recursion immediately.  So we parse out a primary expression to start with.
5001            const pos = getNodePos();
5002            let expression;
5003
5004            if (inEtsExtendComponentsContext() && extendEtsComponentDeclaration && token() === SyntaxKind.DotToken) {
5005                expression = finishVirtualNode(factory.createIdentifier(extendEtsComponentDeclaration.instance, /*typeArguments*/ undefined, SyntaxKind.Identifier), pos, pos);
5006            }
5007            else if (inEtsStylesComponentsContext() && stylesEtsComponentDeclaration && token() === SyntaxKind.DotToken) {
5008                expression = finishVirtualNode(factory.createIdentifier(stylesEtsComponentDeclaration.instance, /*typeArguments*/ undefined, SyntaxKind.Identifier), pos, pos);
5009            }
5010            else if (inEtsStateStylesContext() && stateStylesRootNode && token() === SyntaxKind.DotToken) {
5011                expression = finishVirtualNode(factory.createIdentifier(`${stateStylesRootNode}Instance`, /*typeArguments*/ undefined, SyntaxKind.Identifier), pos, pos);
5012            }
5013            else {
5014                expression = parsePrimaryExpression();
5015            }
5016            return parseMemberExpressionRest(pos, expression, /*allowOptionalChain*/ true);
5017        }
5018
5019        function parseSuperExpression(): MemberExpression {
5020            const pos = getNodePos();
5021            const expression = parseTokenNode<PrimaryExpression>();
5022            if (token() === SyntaxKind.LessThanToken) {
5023                const startPos = getNodePos();
5024                const typeArguments = tryParse(parseTypeArgumentsInExpression);
5025                if (typeArguments !== undefined) {
5026                    parseErrorAt(startPos, getNodePos(), Diagnostics.super_may_not_use_type_arguments);
5027                }
5028            }
5029
5030            if (token() === SyntaxKind.OpenParenToken || token() === SyntaxKind.DotToken || token() === SyntaxKind.OpenBracketToken) {
5031                return expression;
5032            }
5033
5034            // If we have seen "super" it must be followed by '(' or '.'.
5035            // If it wasn't then just try to parse out a '.' and report an error.
5036            parseExpectedToken(SyntaxKind.DotToken, Diagnostics.super_must_be_followed_by_an_argument_list_or_member_access);
5037            // private names will never work with `super` (`super.#foo`), but that's a semantic error, not syntactic
5038            return finishNode(factory.createPropertyAccessExpression(expression, parseRightSideOfDot(/*allowIdentifierNames*/ true, /*allowPrivateIdentifiers*/ true)), pos);
5039        }
5040
5041        function parseJsxElementOrSelfClosingElementOrFragment(inExpressionContext: boolean, topInvalidNodePosition?: number): JsxElement | JsxSelfClosingElement | JsxFragment {
5042            const pos = getNodePos();
5043            const opening = parseJsxOpeningOrSelfClosingElementOrOpeningFragment(inExpressionContext);
5044            let result: JsxElement | JsxSelfClosingElement | JsxFragment;
5045            if (opening.kind === SyntaxKind.JsxOpeningElement) {
5046                const children = parseJsxChildren(opening);
5047                const closingElement = parseJsxClosingElement(inExpressionContext);
5048
5049                if (!tagNamesAreEquivalent(opening.tagName, closingElement.tagName)) {
5050                    parseErrorAtRange(closingElement, Diagnostics.Expected_corresponding_JSX_closing_tag_for_0, getTextOfNodeFromSourceText(sourceText, opening.tagName));
5051                }
5052
5053                result = finishNode(factory.createJsxElement(opening, children, closingElement), pos);
5054            }
5055            else if (opening.kind === SyntaxKind.JsxOpeningFragment) {
5056                result = finishNode(factory.createJsxFragment(opening, parseJsxChildren(opening), parseJsxClosingFragment(inExpressionContext)), pos);
5057            }
5058            else {
5059                Debug.assert(opening.kind === SyntaxKind.JsxSelfClosingElement);
5060                // Nothing else to do for self-closing elements
5061                result = opening;
5062            }
5063
5064            // If the user writes the invalid code '<div></div><div></div>' in an expression context (i.e. not wrapped in
5065            // an enclosing tag), we'll naively try to parse   ^ this as a 'less than' operator and the remainder of the tag
5066            // as garbage, which will cause the formatter to badly mangle the JSX. Perform a speculative parse of a JSX
5067            // element if we see a < token so that we can wrap it in a synthetic binary expression so the formatter
5068            // does less damage and we can report a better error.
5069            // Since JSX elements are invalid < operands anyway, this lookahead parse will only occur in error scenarios
5070            // of one sort or another.
5071            if (inExpressionContext && token() === SyntaxKind.LessThanToken) {
5072                const topBadPos = typeof topInvalidNodePosition === "undefined" ? result.pos : topInvalidNodePosition;
5073                const invalidElement = tryParse(() => parseJsxElementOrSelfClosingElementOrFragment(/*inExpressionContext*/ true, topBadPos));
5074                if (invalidElement) {
5075                    const operatorToken = createMissingNode(SyntaxKind.CommaToken, /*reportAtCurrentPosition*/ false);
5076                    setTextRangePosWidth(operatorToken, invalidElement.pos, 0);
5077                    parseErrorAt(skipTrivia(sourceText, topBadPos), invalidElement.end, Diagnostics.JSX_expressions_must_have_one_parent_element);
5078                    return <JsxElement><Node>finishNode(factory.createBinaryExpression(result, operatorToken as Token<SyntaxKind.CommaToken>, invalidElement), pos);
5079                }
5080            }
5081
5082            return result;
5083        }
5084
5085        function parseJsxText(): JsxText {
5086            const pos = getNodePos();
5087            const node = factory.createJsxText(scanner.getTokenValue(), currentToken === SyntaxKind.JsxTextAllWhiteSpaces);
5088            currentToken = scanner.scanJsxToken();
5089            return finishNode(node, pos);
5090        }
5091
5092        function parseJsxChild(openingTag: JsxOpeningElement | JsxOpeningFragment, token: JsxTokenSyntaxKind): JsxChild | undefined {
5093            switch (token) {
5094                case SyntaxKind.EndOfFileToken:
5095                    // If we hit EOF, issue the error at the tag that lacks the closing element
5096                    // rather than at the end of the file (which is useless)
5097                    if (isJsxOpeningFragment(openingTag)) {
5098                        parseErrorAtRange(openingTag, Diagnostics.JSX_fragment_has_no_corresponding_closing_tag);
5099                    }
5100                    else {
5101                        // We want the error span to cover only 'Foo.Bar' in < Foo.Bar >
5102                        // or to cover only 'Foo' in < Foo >
5103                        const tag = openingTag.tagName;
5104                        const start = skipTrivia(sourceText, tag.pos);
5105                        parseErrorAt(start, tag.end, Diagnostics.JSX_element_0_has_no_corresponding_closing_tag, getTextOfNodeFromSourceText(sourceText, openingTag.tagName));
5106                    }
5107                    return undefined;
5108                case SyntaxKind.LessThanSlashToken:
5109                case SyntaxKind.ConflictMarkerTrivia:
5110                    return undefined;
5111                case SyntaxKind.JsxText:
5112                case SyntaxKind.JsxTextAllWhiteSpaces:
5113                    return parseJsxText();
5114                case SyntaxKind.OpenBraceToken:
5115                    return parseJsxExpression(/*inExpressionContext*/ false);
5116                case SyntaxKind.LessThanToken:
5117                    return parseJsxElementOrSelfClosingElementOrFragment(/*inExpressionContext*/ false);
5118                default:
5119                    return Debug.assertNever(token);
5120            }
5121        }
5122
5123        function parseJsxChildren(openingTag: JsxOpeningElement | JsxOpeningFragment): NodeArray<JsxChild> {
5124            const list = [];
5125            const listPos = getNodePos();
5126            const saveParsingContext = parsingContext;
5127            parsingContext |= 1 << ParsingContext.JsxChildren;
5128
5129            while (true) {
5130                const child = parseJsxChild(openingTag, currentToken = scanner.reScanJsxToken());
5131                if (!child) break;
5132                list.push(child);
5133            }
5134
5135            parsingContext = saveParsingContext;
5136            return createNodeArray(list, listPos);
5137        }
5138
5139        function parseJsxAttributes(): JsxAttributes {
5140            const pos = getNodePos();
5141            return finishNode(factory.createJsxAttributes(parseList(ParsingContext.JsxAttributes, parseJsxAttribute)), pos);
5142        }
5143
5144        function parseJsxOpeningOrSelfClosingElementOrOpeningFragment(inExpressionContext: boolean): JsxOpeningElement | JsxSelfClosingElement | JsxOpeningFragment {
5145            const pos = getNodePos();
5146
5147            parseExpected(SyntaxKind.LessThanToken);
5148
5149            if (token() === SyntaxKind.GreaterThanToken) {
5150                // See below for explanation of scanJsxText
5151                scanJsxText();
5152                return finishNode(factory.createJsxOpeningFragment(), pos);
5153            }
5154
5155            const tagName = parseJsxElementName();
5156            const typeArguments = (contextFlags & NodeFlags.JavaScriptFile) === 0 ? tryParseTypeArguments() : undefined;
5157            const attributes = parseJsxAttributes();
5158
5159            let node: JsxOpeningLikeElement;
5160
5161            if (token() === SyntaxKind.GreaterThanToken) {
5162                // Closing tag, so scan the immediately-following text with the JSX scanning instead
5163                // of regular scanning to avoid treating illegal characters (e.g. '#') as immediate
5164                // scanning errors
5165                scanJsxText();
5166                node = factory.createJsxOpeningElement(tagName, typeArguments, attributes);
5167            }
5168            else {
5169                parseExpected(SyntaxKind.SlashToken);
5170                if (inExpressionContext) {
5171                    parseExpected(SyntaxKind.GreaterThanToken);
5172                }
5173                else {
5174                    parseExpected(SyntaxKind.GreaterThanToken, /*diagnostic*/ undefined, /*shouldAdvance*/ false);
5175                    scanJsxText();
5176                }
5177                node = factory.createJsxSelfClosingElement(tagName, typeArguments, attributes);
5178            }
5179
5180            return finishNode(node, pos);
5181        }
5182
5183        function parseJsxElementName(): JsxTagNameExpression {
5184            const pos = getNodePos();
5185            scanJsxIdentifier();
5186            // JsxElement can have name in the form of
5187            //      propertyAccessExpression
5188            //      primaryExpression in the form of an identifier and "this" keyword
5189            // We can't just simply use parseLeftHandSideExpressionOrHigher because then we will start consider class,function etc as a keyword
5190            // We only want to consider "this" as a primaryExpression
5191            let expression: JsxTagNameExpression = token() === SyntaxKind.ThisKeyword ?
5192                parseTokenNode<ThisExpression>() : parseIdentifierName();
5193            while (parseOptional(SyntaxKind.DotToken)) {
5194                expression = finishNode(factory.createPropertyAccessExpression(expression, parseRightSideOfDot(/*allowIdentifierNames*/ true, /*allowPrivateIdentifiers*/ false)), pos) as JsxTagNamePropertyAccess;
5195            }
5196            return expression;
5197        }
5198
5199        function parseJsxExpression(inExpressionContext: boolean): JsxExpression | undefined {
5200            const pos = getNodePos();
5201            if (!parseExpected(SyntaxKind.OpenBraceToken)) {
5202                return undefined;
5203            }
5204
5205            let dotDotDotToken: DotDotDotToken | undefined;
5206            let expression: Expression | undefined;
5207            if (token() !== SyntaxKind.CloseBraceToken) {
5208                dotDotDotToken = parseOptionalToken(SyntaxKind.DotDotDotToken);
5209                // Only an AssignmentExpression is valid here per the JSX spec,
5210                // but we can unambiguously parse a comma sequence and provide
5211                // a better error message in grammar checking.
5212                expression = parseExpression();
5213            }
5214            if (inExpressionContext) {
5215                parseExpected(SyntaxKind.CloseBraceToken);
5216            }
5217            else {
5218                if (parseExpected(SyntaxKind.CloseBraceToken, /*message*/ undefined, /*shouldAdvance*/ false)) {
5219                    scanJsxText();
5220                }
5221            }
5222
5223            return finishNode(factory.createJsxExpression(dotDotDotToken, expression), pos);
5224        }
5225
5226        function parseJsxAttribute(): JsxAttribute | JsxSpreadAttribute {
5227            if (token() === SyntaxKind.OpenBraceToken) {
5228                return parseJsxSpreadAttribute();
5229            }
5230
5231            scanJsxIdentifier();
5232            const pos = getNodePos();
5233            return finishNode(
5234                factory.createJsxAttribute(
5235                    parseIdentifierName(),
5236                    token() !== SyntaxKind.EqualsToken ? undefined :
5237                    scanJsxAttributeValue() === SyntaxKind.StringLiteral ? parseLiteralNode() as StringLiteral :
5238                    parseJsxExpression(/*inExpressionContext*/ true)
5239                ),
5240                pos
5241            );
5242        }
5243
5244        function parseJsxSpreadAttribute(): JsxSpreadAttribute {
5245            const pos = getNodePos();
5246            parseExpected(SyntaxKind.OpenBraceToken);
5247            parseExpected(SyntaxKind.DotDotDotToken);
5248            const expression = parseExpression();
5249            parseExpected(SyntaxKind.CloseBraceToken);
5250            return finishNode(factory.createJsxSpreadAttribute(expression), pos);
5251        }
5252
5253        function parseJsxClosingElement(inExpressionContext: boolean): JsxClosingElement {
5254            const pos = getNodePos();
5255            parseExpected(SyntaxKind.LessThanSlashToken);
5256            const tagName = parseJsxElementName();
5257            if (inExpressionContext) {
5258                parseExpected(SyntaxKind.GreaterThanToken);
5259            }
5260            else {
5261                parseExpected(SyntaxKind.GreaterThanToken, /*diagnostic*/ undefined, /*shouldAdvance*/ false);
5262                scanJsxText();
5263            }
5264            return finishNode(factory.createJsxClosingElement(tagName), pos);
5265        }
5266
5267        function parseJsxClosingFragment(inExpressionContext: boolean): JsxClosingFragment {
5268            const pos = getNodePos();
5269            parseExpected(SyntaxKind.LessThanSlashToken);
5270            if (tokenIsIdentifierOrKeyword(token())) {
5271                parseErrorAtRange(parseJsxElementName(), Diagnostics.Expected_corresponding_closing_tag_for_JSX_fragment);
5272            }
5273            if (inExpressionContext) {
5274                parseExpected(SyntaxKind.GreaterThanToken);
5275            }
5276            else {
5277                parseExpected(SyntaxKind.GreaterThanToken, /*diagnostic*/ undefined, /*shouldAdvance*/ false);
5278                scanJsxText();
5279            }
5280            return finishNode(factory.createJsxJsxClosingFragment(), pos);
5281        }
5282
5283        function parseTypeAssertion(): TypeAssertion {
5284            const pos = getNodePos();
5285            parseExpected(SyntaxKind.LessThanToken);
5286            const type = parseType();
5287            parseExpected(SyntaxKind.GreaterThanToken);
5288            const expression = parseSimpleUnaryExpression();
5289            return finishNode(factory.createTypeAssertion(type, expression), pos);
5290        }
5291
5292        function nextTokenIsIdentifierOrKeywordOrOpenBracketOrTemplate() {
5293            nextToken();
5294            return tokenIsIdentifierOrKeyword(token())
5295                || token() === SyntaxKind.OpenBracketToken
5296                || isTemplateStartOfTaggedTemplate();
5297        }
5298
5299        function isStartOfOptionalPropertyOrElementAccessChain() {
5300            return token() === SyntaxKind.QuestionDotToken
5301                && lookAhead(nextTokenIsIdentifierOrKeywordOrOpenBracketOrTemplate);
5302        }
5303
5304        function tryReparseOptionalChain(node: Expression) {
5305            if (node.flags & NodeFlags.OptionalChain) {
5306                return true;
5307            }
5308            // check for an optional chain in a non-null expression
5309            if (isNonNullExpression(node)) {
5310                let expr = node.expression;
5311                while (isNonNullExpression(expr) && !(expr.flags & NodeFlags.OptionalChain)) {
5312                    expr = expr.expression;
5313                }
5314                if (expr.flags & NodeFlags.OptionalChain) {
5315                    // this is part of an optional chain. Walk down from `node` to `expression` and set the flag.
5316                    while (isNonNullExpression(node)) {
5317                        (node as Mutable<NonNullExpression>).flags |= NodeFlags.OptionalChain;
5318                        node = node.expression;
5319                    }
5320                    return true;
5321                }
5322            }
5323            return false;
5324        }
5325
5326        function parsePropertyAccessExpressionRest(pos: number, expression: LeftHandSideExpression, questionDotToken: QuestionDotToken | undefined) {
5327            const name = parseRightSideOfDot(/*allowIdentifierNames*/ true, /*allowPrivateIdentifiers*/ true);
5328            const isOptionalChain = questionDotToken || tryReparseOptionalChain(expression);
5329            const propertyAccess = isOptionalChain ?
5330                factory.createPropertyAccessChain(expression, questionDotToken, name) :
5331                factory.createPropertyAccessExpression(expression, name);
5332            if (isOptionalChain && isPrivateIdentifier(propertyAccess.name)) {
5333                parseErrorAtRange(propertyAccess.name, Diagnostics.An_optional_chain_cannot_contain_private_identifiers);
5334            }
5335            return finishNode(propertyAccess, pos);
5336        }
5337
5338        function parseElementAccessExpressionRest(pos: number, expression: LeftHandSideExpression, questionDotToken: QuestionDotToken | undefined) {
5339            let argumentExpression: Expression;
5340            if (token() === SyntaxKind.CloseBracketToken) {
5341                argumentExpression = createMissingNode(SyntaxKind.Identifier, /*reportAtCurrentPosition*/ true, Diagnostics.An_element_access_expression_should_take_an_argument);
5342            }
5343            else {
5344                const argument = allowInAnd(parseExpression);
5345                if (isStringOrNumericLiteralLike(argument)) {
5346                    argument.text = internIdentifier(argument.text);
5347                }
5348                argumentExpression = argument;
5349            }
5350
5351            parseExpected(SyntaxKind.CloseBracketToken);
5352
5353            const indexedAccess = questionDotToken || tryReparseOptionalChain(expression) ?
5354                factory.createElementAccessChain(expression, questionDotToken, argumentExpression) :
5355                factory.createElementAccessExpression(expression, argumentExpression);
5356            return finishNode(indexedAccess, pos);
5357        }
5358
5359        function parseMemberExpressionRest(pos: number, expression: LeftHandSideExpression, allowOptionalChain: boolean): MemberExpression {
5360            while (true) {
5361                let questionDotToken: QuestionDotToken | undefined;
5362                let isPropertyAccess = false;
5363                if (allowOptionalChain && isStartOfOptionalPropertyOrElementAccessChain()) {
5364                    questionDotToken = parseExpectedToken(SyntaxKind.QuestionDotToken);
5365                    isPropertyAccess = tokenIsIdentifierOrKeyword(token());
5366                }
5367                else {
5368                    isPropertyAccess = parseOptional(SyntaxKind.DotToken);
5369                }
5370
5371                if (isPropertyAccess) {
5372                    expression = parsePropertyAccessExpressionRest(pos, expression, questionDotToken);
5373                    continue;
5374                }
5375
5376                if (!questionDotToken && token() === SyntaxKind.ExclamationToken && !scanner.hasPrecedingLineBreak()) {
5377                    nextToken();
5378                    expression = finishNode(factory.createNonNullExpression(expression), pos);
5379                    continue;
5380                }
5381
5382                // when in the [Decorator] context, we do not parse ElementAccess as it could be part of a ComputedPropertyName
5383                if ((questionDotToken || !inDecoratorContext()) && parseOptional(SyntaxKind.OpenBracketToken)) {
5384                    expression = parseElementAccessExpressionRest(pos, expression, questionDotToken);
5385                    continue;
5386                }
5387
5388                if (isTemplateStartOfTaggedTemplate()) {
5389                    expression = parseTaggedTemplateRest(pos, expression, questionDotToken, /*typeArguments*/ undefined);
5390                    continue;
5391                }
5392
5393                return <MemberExpression>expression;
5394            }
5395        }
5396
5397        function isTemplateStartOfTaggedTemplate() {
5398            return token() === SyntaxKind.NoSubstitutionTemplateLiteral || token() === SyntaxKind.TemplateHead;
5399        }
5400
5401        function parseTaggedTemplateRest(pos: number, tag: LeftHandSideExpression, questionDotToken: QuestionDotToken | undefined, typeArguments: NodeArray<TypeNode> | undefined) {
5402            const tagExpression = factory.createTaggedTemplateExpression(
5403                tag,
5404                typeArguments,
5405                token() === SyntaxKind.NoSubstitutionTemplateLiteral ?
5406                    (reScanTemplateHeadOrNoSubstitutionTemplate(), parseLiteralNode() as NoSubstitutionTemplateLiteral) :
5407                    parseTemplateExpression(/*isTaggedTemplate*/ true)
5408            );
5409            if (questionDotToken || tag.flags & NodeFlags.OptionalChain) {
5410                (tagExpression as Mutable<Node>).flags |= NodeFlags.OptionalChain;
5411            }
5412            tagExpression.questionDotToken = questionDotToken;
5413            return finishNode(tagExpression, pos);
5414        }
5415
5416        function parseCallExpressionRest(pos: number, expression: LeftHandSideExpression): LeftHandSideExpression {
5417            let currentNodeName: string | undefined;
5418            while (true) {
5419                expression = parseMemberExpressionRest(pos, expression, /*allowOptionalChain*/ true);
5420                const questionDotToken = parseOptionalToken(SyntaxKind.QuestionDotToken);
5421                // handle 'foo<<T>()'
5422                // parse template arguments only in TypeScript files (not in JavaScript files).
5423                if ((contextFlags & NodeFlags.JavaScriptFile) === 0 && (token() === SyntaxKind.LessThanToken || token() === SyntaxKind.LessThanLessThanToken)) {
5424                    // See if this is the start of a generic invocation.  If so, consume it and
5425                    // keep checking for postfix expressions.  Otherwise, it's just a '<' that's
5426                    // part of an arithmetic expression.  Break out so we consume it higher in the
5427                    // stack.
5428                    const typeArguments = tryParse(parseTypeArgumentsInExpression);
5429                    if (typeArguments) {
5430                        if (isTemplateStartOfTaggedTemplate()) {
5431                            expression = parseTaggedTemplateRest(pos, expression, questionDotToken, typeArguments);
5432                            continue;
5433                        }
5434
5435                        const argumentList = parseArgumentList();
5436                        const callExpr = questionDotToken || tryReparseOptionalChain(expression) ?
5437                            factory.createCallChain(expression, questionDotToken, typeArguments, argumentList) :
5438                            factory.createCallExpression(expression, typeArguments, argumentList);
5439                        expression = finishNode(callExpr, pos);
5440                        continue;
5441                    }
5442                }
5443                else if (token() === SyntaxKind.OpenParenToken) {
5444                    let typeArguments: NodeArray<TypeNode> | undefined;
5445                    if ((isValidVirtualTypeArgumentsContext() || inBuilderContext()) && isPropertyAccessExpression(expression)) {
5446                        const rootNode = getRootEtsComponent(expression);
5447                        if (rootNode) {
5448                            const rootNodeName = (<Identifier>(rootNode.expression)).escapedText.toString();
5449                            currentNodeName = getTextOfPropertyName(expression.name).toString();
5450                            if (currentNodeName === sourceFileCompilerOptions?.ets?.styles?.property) {
5451                                setEtsStateStylesContext(true);
5452                                stateStylesRootNode = rootNodeName;
5453                            }
5454                            else {
5455                                setEtsStateStylesContext(false);
5456                                stateStylesRootNode = undefined;
5457                            }
5458                            typeArguments = parseEtsTypeArguments(pos, `${rootNodeName}Attribute`);
5459                        }
5460                        else if (inEtsStateStylesContext() && stateStylesRootNode) {
5461                            typeArguments = parseEtsTypeArguments(pos, `${stateStylesRootNode}Attribute`);
5462                        }
5463                    }
5464                    const argumentList = parseArgumentList();
5465                    const callExpr = questionDotToken || tryReparseOptionalChain(expression) ?
5466                        factory.createCallChain(expression, questionDotToken, typeArguments, argumentList) :
5467                        factory.createCallExpression(expression, typeArguments, argumentList);
5468                    expression = finishNode(callExpr, pos);
5469                    continue;
5470                }
5471                if (questionDotToken) {
5472                    // We failed to parse anything, so report a missing identifier here.
5473                    const name = createMissingNode<Identifier>(SyntaxKind.Identifier, /*reportAtCurrentPosition*/ false, Diagnostics.Identifier_expected);
5474                    expression = finishNode(factory.createPropertyAccessChain(expression, questionDotToken, name), pos);
5475                }
5476                break;
5477            }
5478            if (currentNodeName === sourceFileCompilerOptions?.ets?.styles?.property) {
5479                setEtsStateStylesContext(false);
5480                stateStylesRootNode = undefined;
5481            }
5482            return expression;
5483        }
5484
5485        function isValidVirtualTypeArgumentsContext(): boolean {
5486            return (inBuildContext() || inBuilderContext()) && inStructContext();
5487        }
5488
5489        function parseArgumentList() {
5490            parseExpected(SyntaxKind.OpenParenToken);
5491            const result = parseDelimitedList(ParsingContext.ArgumentExpressions, parseArgumentExpression);
5492            parseExpected(SyntaxKind.CloseParenToken);
5493            return result;
5494        }
5495
5496        function parseTypeArgumentsInExpression() {
5497            if ((contextFlags & NodeFlags.JavaScriptFile) !== 0) {
5498                // TypeArguments must not be parsed in JavaScript files to avoid ambiguity with binary operators.
5499                return undefined;
5500            }
5501
5502            if (reScanLessThanToken() !== SyntaxKind.LessThanToken) {
5503                return undefined;
5504            }
5505            nextToken();
5506
5507            const typeArguments = parseDelimitedList(ParsingContext.TypeArguments, parseType);
5508            if (!parseExpected(SyntaxKind.GreaterThanToken)) {
5509                // If it doesn't have the closing `>` then it's definitely not an type argument list.
5510                return undefined;
5511            }
5512
5513            // If we have a '<', then only parse this as a argument list if the type arguments
5514            // are complete and we have an open paren.  if we don't, rewind and return nothing.
5515            return typeArguments && canFollowTypeArgumentsInExpression()
5516                ? typeArguments
5517                : undefined;
5518        }
5519
5520        function canFollowTypeArgumentsInExpression(): boolean {
5521            switch (token()) {
5522                case SyntaxKind.OpenParenToken:                 // foo<x>(
5523                case SyntaxKind.NoSubstitutionTemplateLiteral:  // foo<T> `...`
5524                case SyntaxKind.TemplateHead:                   // foo<T> `...${100}...`
5525                // these are the only tokens can legally follow a type argument
5526                // list. So we definitely want to treat them as type arg lists.
5527                // falls through
5528                case SyntaxKind.DotToken:                       // foo<x>.
5529                case SyntaxKind.CloseParenToken:                // foo<x>)
5530                case SyntaxKind.CloseBracketToken:              // foo<x>]
5531                case SyntaxKind.ColonToken:                     // foo<x>:
5532                case SyntaxKind.SemicolonToken:                 // foo<x>;
5533                case SyntaxKind.QuestionToken:                  // foo<x>?
5534                case SyntaxKind.EqualsEqualsToken:              // foo<x> ==
5535                case SyntaxKind.EqualsEqualsEqualsToken:        // foo<x> ===
5536                case SyntaxKind.ExclamationEqualsToken:         // foo<x> !=
5537                case SyntaxKind.ExclamationEqualsEqualsToken:   // foo<x> !==
5538                case SyntaxKind.AmpersandAmpersandToken:        // foo<x> &&
5539                case SyntaxKind.BarBarToken:                    // foo<x> ||
5540                case SyntaxKind.QuestionQuestionToken:          // foo<x> ??
5541                case SyntaxKind.CaretToken:                     // foo<x> ^
5542                case SyntaxKind.AmpersandToken:                 // foo<x> &
5543                case SyntaxKind.BarToken:                       // foo<x> |
5544                case SyntaxKind.CloseBraceToken:                // foo<x> }
5545                case SyntaxKind.EndOfFileToken:                 // foo<x>
5546                    // these cases can't legally follow a type arg list.  However, they're not legal
5547                    // expressions either.  The user is probably in the middle of a generic type. So
5548                    // treat it as such.
5549                    return true;
5550
5551                case SyntaxKind.CommaToken:                     // foo<x>,
5552                case SyntaxKind.OpenBraceToken:                 // foo<x> {
5553                // We don't want to treat these as type arguments.  Otherwise we'll parse this
5554                // as an invocation expression.  Instead, we want to parse out the expression
5555                // in isolation from the type arguments.
5556                // falls through
5557                default:
5558                    // Anything else treat as an expression.
5559                    return false;
5560            }
5561        }
5562
5563        function isCurrentTokenAnEtsComponentExpression(): boolean {
5564            if (!inEtsComponentsContext()) {
5565                return false;
5566            }
5567            const components = sourceFileCompilerOptions.ets?.components ?? [];
5568            return components.includes(scanner.getTokenText());
5569        }
5570
5571        function parsePrimaryExpression(): PrimaryExpression {
5572            switch (token()) {
5573                case SyntaxKind.NumericLiteral:
5574                case SyntaxKind.BigIntLiteral:
5575                case SyntaxKind.StringLiteral:
5576                case SyntaxKind.NoSubstitutionTemplateLiteral:
5577                    return parseLiteralNode();
5578                case SyntaxKind.ThisKeyword:
5579                case SyntaxKind.SuperKeyword:
5580                case SyntaxKind.NullKeyword:
5581                case SyntaxKind.TrueKeyword:
5582                case SyntaxKind.FalseKeyword:
5583                    return parseTokenNode<PrimaryExpression>();
5584                case SyntaxKind.OpenParenToken:
5585                    return parseParenthesizedExpression();
5586                case SyntaxKind.OpenBracketToken:
5587                    return parseArrayLiteralExpression();
5588                case SyntaxKind.OpenBraceToken:
5589                    return parseObjectLiteralExpression();
5590                case SyntaxKind.AsyncKeyword:
5591                    // Async arrow functions are parsed earlier in parseAssignmentExpressionOrHigher.
5592                    // If we encounter `async [no LineTerminator here] function` then this is an async
5593                    // function; otherwise, its an identifier.
5594                    if (!lookAhead(nextTokenIsFunctionKeywordOnSameLine)) {
5595                        break;
5596                    }
5597
5598                    return parseFunctionExpression();
5599                case SyntaxKind.ClassKeyword:
5600                    return parseClassExpression();
5601                case SyntaxKind.FunctionKeyword:
5602                    return parseFunctionExpression();
5603                case SyntaxKind.NewKeyword:
5604                    return parseNewExpressionOrNewDotTarget();
5605                case SyntaxKind.SlashToken:
5606                case SyntaxKind.SlashEqualsToken:
5607                    if (reScanSlashToken() === SyntaxKind.RegularExpressionLiteral) {
5608                        return parseLiteralNode();
5609                    }
5610                    break;
5611                case SyntaxKind.TemplateHead:
5612                    return parseTemplateExpression(/* isTaggedTemplate */ false);
5613            }
5614
5615            if(isCurrentTokenAnEtsComponentExpression() && !inEtsNewExpressionContext()){
5616                return parseEtsComponentExpression();
5617            }
5618
5619            return parseIdentifier(Diagnostics.Expression_expected);
5620        }
5621
5622        function parseParenthesizedExpression(): ParenthesizedExpression {
5623            const pos = getNodePos();
5624            const hasJSDoc = hasPrecedingJSDocComment();
5625            parseExpected(SyntaxKind.OpenParenToken);
5626            const expression = allowInAnd(parseExpression);
5627            parseExpected(SyntaxKind.CloseParenToken);
5628            return withJSDoc(finishNode(factory.createParenthesizedExpression(expression), pos), hasJSDoc);
5629        }
5630
5631        function parseSpreadElement(): Expression {
5632            const pos = getNodePos();
5633            parseExpected(SyntaxKind.DotDotDotToken);
5634            const expression = parseAssignmentExpressionOrHigher();
5635            return finishNode(factory.createSpreadElement(expression), pos);
5636        }
5637
5638        function parseArgumentOrArrayLiteralElement(): Expression {
5639            return token() === SyntaxKind.DotDotDotToken ? parseSpreadElement() :
5640                token() === SyntaxKind.CommaToken ? finishNode(factory.createOmittedExpression(), getNodePos()) :
5641                parseAssignmentExpressionOrHigher();
5642        }
5643
5644        function parseArgumentExpression(): Expression {
5645            return doOutsideOfContext(disallowInAndDecoratorContext, parseArgumentOrArrayLiteralElement);
5646        }
5647
5648        function parseArrayLiteralExpression(): ArrayLiteralExpression {
5649            const pos = getNodePos();
5650            parseExpected(SyntaxKind.OpenBracketToken);
5651            const multiLine = scanner.hasPrecedingLineBreak();
5652            const elements = parseDelimitedList(ParsingContext.ArrayLiteralMembers, parseArgumentOrArrayLiteralElement);
5653            parseExpected(SyntaxKind.CloseBracketToken);
5654            return finishNode(factory.createArrayLiteralExpression(elements, multiLine), pos);
5655        }
5656
5657        function parseObjectLiteralElement(): ObjectLiteralElementLike {
5658            const pos = getNodePos();
5659            const hasJSDoc = hasPrecedingJSDocComment();
5660
5661            if (parseOptionalToken(SyntaxKind.DotDotDotToken)) {
5662                const expression = parseAssignmentExpressionOrHigher();
5663                return withJSDoc(finishNode(factory.createSpreadAssignment(expression), pos), hasJSDoc);
5664            }
5665
5666            const decorators = parseDecorators();
5667            const modifiers = parseModifiers();
5668
5669            if (parseContextualModifier(SyntaxKind.GetKeyword)) {
5670                return parseAccessorDeclaration(pos, hasJSDoc, decorators, modifiers, SyntaxKind.GetAccessor);
5671            }
5672            if (parseContextualModifier(SyntaxKind.SetKeyword)) {
5673                return parseAccessorDeclaration(pos, hasJSDoc, decorators, modifiers, SyntaxKind.SetAccessor);
5674            }
5675
5676            const asteriskToken = parseOptionalToken(SyntaxKind.AsteriskToken);
5677            const tokenIsIdentifier = isIdentifier();
5678            const name = parsePropertyName();
5679
5680            // Disallowing of optional property assignments and definite assignment assertion happens in the grammar checker.
5681            const questionToken = parseOptionalToken(SyntaxKind.QuestionToken);
5682            const exclamationToken = parseOptionalToken(SyntaxKind.ExclamationToken);
5683
5684            if (asteriskToken || token() === SyntaxKind.OpenParenToken || token() === SyntaxKind.LessThanToken) {
5685                return parseMethodDeclaration(pos, hasJSDoc, decorators, modifiers, asteriskToken, name, questionToken, exclamationToken);
5686            }
5687
5688            // check if it is short-hand property assignment or normal property assignment
5689            // NOTE: if token is EqualsToken it is interpreted as CoverInitializedName production
5690            // CoverInitializedName[Yield] :
5691            //     IdentifierReference[?Yield] Initializer[In, ?Yield]
5692            // this is necessary because ObjectLiteral productions are also used to cover grammar for ObjectAssignmentPattern
5693            let node: Mutable<ShorthandPropertyAssignment | PropertyAssignment>;
5694            const isShorthandPropertyAssignment = tokenIsIdentifier && (token() !== SyntaxKind.ColonToken);
5695            if (isShorthandPropertyAssignment) {
5696                const equalsToken = parseOptionalToken(SyntaxKind.EqualsToken);
5697                const objectAssignmentInitializer = equalsToken ? allowInAnd(parseAssignmentExpressionOrHigher) : undefined;
5698                node = factory.createShorthandPropertyAssignment(name as Identifier, objectAssignmentInitializer);
5699                // Save equals token for error reporting.
5700                // TODO(rbuckton): Consider manufacturing this when we need to report an error as it is otherwise not useful.
5701                node.equalsToken = equalsToken;
5702            }
5703            else {
5704                parseExpected(SyntaxKind.ColonToken);
5705                const initializer = allowInAnd(parseAssignmentExpressionOrHigher);
5706                node = factory.createPropertyAssignment(name, initializer);
5707            }
5708            // Decorators, Modifiers, questionToken, and exclamationToken are not supported by property assignments and are reported in the grammar checker
5709            node.decorators = decorators;
5710            node.modifiers = modifiers;
5711            node.questionToken = questionToken;
5712            node.exclamationToken = exclamationToken;
5713            return withJSDoc(finishNode(node, pos), hasJSDoc);
5714        }
5715
5716        function parseObjectLiteralExpression(): ObjectLiteralExpression {
5717            const pos = getNodePos();
5718            const openBracePosition = scanner.getTokenPos();
5719            parseExpected(SyntaxKind.OpenBraceToken);
5720            const multiLine = scanner.hasPrecedingLineBreak();
5721            const properties = parseDelimitedList(ParsingContext.ObjectLiteralMembers, parseObjectLiteralElement, /*considerSemicolonAsDelimiter*/ true);
5722            if (!parseExpected(SyntaxKind.CloseBraceToken)) {
5723                const lastError = lastOrUndefined(parseDiagnostics);
5724                if (lastError && lastError.code === Diagnostics._0_expected.code) {
5725                    addRelatedInfo(
5726                        lastError,
5727                        createDetachedDiagnostic(fileName, openBracePosition, 1, Diagnostics.The_parser_expected_to_find_a_to_match_the_token_here)
5728                    );
5729                }
5730            }
5731            return finishNode(factory.createObjectLiteralExpression(properties, multiLine), pos);
5732        }
5733
5734        function parseFunctionExpression(): FunctionExpression {
5735            // GeneratorExpression:
5736            //      function* BindingIdentifier [Yield][opt](FormalParameters[Yield]){ GeneratorBody }
5737            //
5738            // FunctionExpression:
5739            //      function BindingIdentifier[opt](FormalParameters){ FunctionBody }
5740            const saveDecoratorContext = inDecoratorContext();
5741            if (saveDecoratorContext) {
5742                setDecoratorContext(/*val*/ false);
5743            }
5744
5745            const pos = getNodePos();
5746            const hasJSDoc = hasPrecedingJSDocComment();
5747            const modifiers = parseModifiers();
5748            parseExpected(SyntaxKind.FunctionKeyword);
5749            const asteriskToken = parseOptionalToken(SyntaxKind.AsteriskToken);
5750            const isGenerator = asteriskToken ? SignatureFlags.Yield : SignatureFlags.None;
5751            const isAsync = some(modifiers, isAsyncModifier) ? SignatureFlags.Await : SignatureFlags.None;
5752            const name =
5753                isGenerator && isAsync ? doInYieldAndAwaitContext(parseOptionalBindingIdentifier) :
5754                isGenerator ? doInYieldContext(parseOptionalBindingIdentifier) :
5755                isAsync ? doInAwaitContext(parseOptionalBindingIdentifier) :
5756                parseOptionalBindingIdentifier();
5757
5758            const typeParameters = parseTypeParameters();
5759            const parameters = parseParameters(isGenerator | isAsync);
5760            const type = parseReturnType(SyntaxKind.ColonToken, /*isType*/ false);
5761            const body = parseFunctionBlock(isGenerator | isAsync);
5762
5763            if (saveDecoratorContext) {
5764                setDecoratorContext(/*val*/ true);
5765            }
5766
5767            const node = factory.createFunctionExpression(modifiers, asteriskToken, name, typeParameters, parameters, type, body);
5768            return withJSDoc(finishNode(node, pos), hasJSDoc);
5769        }
5770
5771        function parseEtsComponentExpression(): EtsComponentExpression {
5772            const pos = getNodePos();
5773            const name = parseBindingIdentifier();
5774            const argumentList = parseArgumentList();
5775            const body = token() === SyntaxKind.OpenBraceToken ? parseFunctionBlock(SignatureFlags.None) : undefined;
5776            const node = factory.createEtsComponentExpression(name, argumentList, body);
5777            return finishNode(node, pos);
5778        }
5779
5780        function parseOptionalBindingIdentifier(): Identifier | undefined {
5781            return isBindingIdentifier() ? parseBindingIdentifier() : undefined;
5782        }
5783
5784        function parseNewExpressionOrNewDotTarget(): NewExpression | MetaProperty {
5785            setEtsNewExpressionContext(inEtsComponentsContext());
5786            const pos = getNodePos();
5787            parseExpected(SyntaxKind.NewKeyword);
5788            if (parseOptional(SyntaxKind.DotToken)) {
5789                const name = parseIdentifierName();
5790                return finishNode(factory.createMetaProperty(SyntaxKind.NewKeyword, name), pos);
5791            }
5792
5793            const expressionPos = getNodePos();
5794            let expression: MemberExpression = parsePrimaryExpression();
5795            let typeArguments;
5796            while (true) {
5797                expression = parseMemberExpressionRest(expressionPos, expression, /*allowOptionalChain*/ false);
5798                typeArguments = tryParse(parseTypeArgumentsInExpression);
5799                if (isTemplateStartOfTaggedTemplate()) {
5800                    Debug.assert(!!typeArguments,
5801                        "Expected a type argument list; all plain tagged template starts should be consumed in 'parseMemberExpressionRest'");
5802                    expression = parseTaggedTemplateRest(expressionPos, expression, /*optionalChain*/ undefined, typeArguments);
5803                    typeArguments = undefined;
5804                }
5805                break;
5806            }
5807
5808            let argumentsArray: NodeArray<Expression> | undefined;
5809            if (token() === SyntaxKind.OpenParenToken) {
5810                argumentsArray = parseArgumentList();
5811            }
5812            else if (typeArguments) {
5813                parseErrorAt(pos, scanner.getStartPos(), Diagnostics.A_new_expression_with_type_arguments_must_always_be_followed_by_a_parenthesized_argument_list);
5814            }
5815            setEtsNewExpressionContext(false);
5816            return finishNode(factory.createNewExpression(expression, typeArguments, argumentsArray), pos);
5817        }
5818
5819        // STATEMENTS
5820        function parseBlock(ignoreMissingOpenBrace: boolean, diagnosticMessage?: DiagnosticMessage): Block {
5821            const pos = getNodePos();
5822            const openBracePosition = scanner.getTokenPos();
5823            if (parseExpected(SyntaxKind.OpenBraceToken, diagnosticMessage) || ignoreMissingOpenBrace) {
5824                const multiLine = scanner.hasPrecedingLineBreak();
5825                const statements = parseList(ParsingContext.BlockStatements, parseStatement);
5826                if (!parseExpected(SyntaxKind.CloseBraceToken)) {
5827                    const lastError = lastOrUndefined(parseDiagnostics);
5828                    if (lastError && lastError.code === Diagnostics._0_expected.code) {
5829                        addRelatedInfo(
5830                            lastError,
5831                            createDetachedDiagnostic(fileName, openBracePosition, 1, Diagnostics.The_parser_expected_to_find_a_to_match_the_token_here)
5832                        );
5833                    }
5834                }
5835                return finishNode(factory.createBlock(statements, multiLine), pos);
5836            }
5837            else {
5838                const statements = createMissingList<Statement>();
5839                return finishNode(factory.createBlock(statements, /*multiLine*/ undefined), pos);
5840            }
5841        }
5842
5843        function parseFunctionBlock(flags: SignatureFlags, diagnosticMessage?: DiagnosticMessage): Block {
5844            const savedYieldContext = inYieldContext();
5845            setYieldContext(!!(flags & SignatureFlags.Yield));
5846
5847            const savedAwaitContext = inAwaitContext();
5848            setAwaitContext(!!(flags & SignatureFlags.Await));
5849
5850            const savedTopLevel = topLevel;
5851            topLevel = false;
5852
5853            // We may be in a [Decorator] context when parsing a function expression or
5854            // arrow function. The body of the function is not in [Decorator] context.
5855            const saveDecoratorContext = inDecoratorContext();
5856            if (saveDecoratorContext) {
5857                setDecoratorContext(/*val*/ false);
5858            }
5859
5860            const block = parseBlock(!!(flags & SignatureFlags.IgnoreMissingOpenBrace), diagnosticMessage);
5861
5862            if (saveDecoratorContext) {
5863                setDecoratorContext(/*val*/ true);
5864            }
5865
5866            topLevel = savedTopLevel;
5867            setYieldContext(savedYieldContext);
5868            setAwaitContext(savedAwaitContext);
5869
5870            return block;
5871        }
5872
5873        function parseEmptyStatement(): Statement {
5874            const pos = getNodePos();
5875            parseExpected(SyntaxKind.SemicolonToken);
5876            return finishNode(factory.createEmptyStatement(), pos);
5877        }
5878
5879        function parseIfStatement(): IfStatement {
5880            const pos = getNodePos();
5881            parseExpected(SyntaxKind.IfKeyword);
5882            parseExpected(SyntaxKind.OpenParenToken);
5883            const expression = allowInAnd(parseExpression);
5884            parseExpected(SyntaxKind.CloseParenToken);
5885            const thenStatement = parseStatement();
5886            const elseStatement = parseOptional(SyntaxKind.ElseKeyword) ? parseStatement() : undefined;
5887            return finishNode(factory.createIfStatement(expression, thenStatement, elseStatement), pos);
5888        }
5889
5890        function parseDoStatement(): DoStatement {
5891            const pos = getNodePos();
5892            parseExpected(SyntaxKind.DoKeyword);
5893            const statement = parseStatement();
5894            parseExpected(SyntaxKind.WhileKeyword);
5895            parseExpected(SyntaxKind.OpenParenToken);
5896            const expression = allowInAnd(parseExpression);
5897            parseExpected(SyntaxKind.CloseParenToken);
5898
5899            // From: https://mail.mozilla.org/pipermail/es-discuss/2011-August/016188.html
5900            // 157 min --- All allen at wirfs-brock.com CONF --- "do{;}while(false)false" prohibited in
5901            // spec but allowed in consensus reality. Approved -- this is the de-facto standard whereby
5902            //  do;while(0)x will have a semicolon inserted before x.
5903            parseOptional(SyntaxKind.SemicolonToken);
5904            return finishNode(factory.createDoStatement(statement, expression), pos);
5905        }
5906
5907        function parseWhileStatement(): WhileStatement {
5908            const pos = getNodePos();
5909            parseExpected(SyntaxKind.WhileKeyword);
5910            parseExpected(SyntaxKind.OpenParenToken);
5911            const expression = allowInAnd(parseExpression);
5912            parseExpected(SyntaxKind.CloseParenToken);
5913            const statement = parseStatement();
5914            return finishNode(factory.createWhileStatement(expression, statement), pos);
5915        }
5916
5917        function parseForOrForInOrForOfStatement(): Statement {
5918            const pos = getNodePos();
5919            parseExpected(SyntaxKind.ForKeyword);
5920            const awaitToken = parseOptionalToken(SyntaxKind.AwaitKeyword);
5921            parseExpected(SyntaxKind.OpenParenToken);
5922
5923            let initializer!: VariableDeclarationList | Expression;
5924            if (token() !== SyntaxKind.SemicolonToken) {
5925                if (token() === SyntaxKind.VarKeyword || token() === SyntaxKind.LetKeyword || token() === SyntaxKind.ConstKeyword) {
5926                    initializer = parseVariableDeclarationList(/*inForStatementInitializer*/ true);
5927                }
5928                else {
5929                    initializer = disallowInAnd(parseExpression);
5930                }
5931            }
5932
5933            let node: IterationStatement;
5934            if (awaitToken ? parseExpected(SyntaxKind.OfKeyword) : parseOptional(SyntaxKind.OfKeyword)) {
5935                const expression = allowInAnd(parseAssignmentExpressionOrHigher);
5936                parseExpected(SyntaxKind.CloseParenToken);
5937                node = factory.createForOfStatement(awaitToken, initializer, expression, parseStatement());
5938            }
5939            else if (parseOptional(SyntaxKind.InKeyword)) {
5940                const expression = allowInAnd(parseExpression);
5941                parseExpected(SyntaxKind.CloseParenToken);
5942                node = factory.createForInStatement(initializer, expression, parseStatement());
5943            }
5944            else {
5945                parseExpected(SyntaxKind.SemicolonToken);
5946                const condition = token() !== SyntaxKind.SemicolonToken && token() !== SyntaxKind.CloseParenToken
5947                    ? allowInAnd(parseExpression)
5948                    : undefined;
5949                parseExpected(SyntaxKind.SemicolonToken);
5950                const incrementor = token() !== SyntaxKind.CloseParenToken
5951                    ? allowInAnd(parseExpression)
5952                    : undefined;
5953                parseExpected(SyntaxKind.CloseParenToken);
5954                node = factory.createForStatement(initializer, condition, incrementor, parseStatement());
5955            }
5956
5957            return finishNode(node, pos);
5958        }
5959
5960        function parseBreakOrContinueStatement(kind: SyntaxKind): BreakOrContinueStatement {
5961            const pos = getNodePos();
5962
5963            parseExpected(kind === SyntaxKind.BreakStatement ? SyntaxKind.BreakKeyword : SyntaxKind.ContinueKeyword);
5964            const label = canParseSemicolon() ? undefined : parseIdentifier();
5965
5966            parseSemicolon();
5967            const node = kind === SyntaxKind.BreakStatement
5968                ? factory.createBreakStatement(label)
5969                : factory.createContinueStatement(label);
5970            return finishNode(node, pos);
5971        }
5972
5973        function parseReturnStatement(): ReturnStatement {
5974            const pos = getNodePos();
5975            parseExpected(SyntaxKind.ReturnKeyword);
5976            const expression = canParseSemicolon() ? undefined : allowInAnd(parseExpression);
5977            parseSemicolon();
5978            return finishNode(factory.createReturnStatement(expression), pos);
5979        }
5980
5981        function parseWithStatement(): WithStatement {
5982            const pos = getNodePos();
5983            parseExpected(SyntaxKind.WithKeyword);
5984            parseExpected(SyntaxKind.OpenParenToken);
5985            const expression = allowInAnd(parseExpression);
5986            parseExpected(SyntaxKind.CloseParenToken);
5987            const statement = doInsideOfContext(NodeFlags.InWithStatement, parseStatement);
5988            return finishNode(factory.createWithStatement(expression, statement), pos);
5989        }
5990
5991        function parseCaseClause(): CaseClause {
5992            const pos = getNodePos();
5993            parseExpected(SyntaxKind.CaseKeyword);
5994            const expression = allowInAnd(parseExpression);
5995            parseExpected(SyntaxKind.ColonToken);
5996            const statements = parseList(ParsingContext.SwitchClauseStatements, parseStatement);
5997            return finishNode(factory.createCaseClause(expression, statements), pos);
5998        }
5999
6000        function parseDefaultClause(): DefaultClause {
6001            const pos = getNodePos();
6002            parseExpected(SyntaxKind.DefaultKeyword);
6003            parseExpected(SyntaxKind.ColonToken);
6004            const statements = parseList(ParsingContext.SwitchClauseStatements, parseStatement);
6005            return finishNode(factory.createDefaultClause(statements), pos);
6006        }
6007
6008        function parseCaseOrDefaultClause(): CaseOrDefaultClause {
6009            return token() === SyntaxKind.CaseKeyword ? parseCaseClause() : parseDefaultClause();
6010        }
6011
6012        function parseCaseBlock(): CaseBlock {
6013            const pos = getNodePos();
6014            parseExpected(SyntaxKind.OpenBraceToken);
6015            const clauses = parseList(ParsingContext.SwitchClauses, parseCaseOrDefaultClause);
6016            parseExpected(SyntaxKind.CloseBraceToken);
6017            return finishNode(factory.createCaseBlock(clauses), pos);
6018        }
6019
6020        function parseSwitchStatement(): SwitchStatement {
6021            const pos = getNodePos();
6022            parseExpected(SyntaxKind.SwitchKeyword);
6023            parseExpected(SyntaxKind.OpenParenToken);
6024            const expression = allowInAnd(parseExpression);
6025            parseExpected(SyntaxKind.CloseParenToken);
6026            const caseBlock = parseCaseBlock();
6027            return finishNode(factory.createSwitchStatement(expression, caseBlock), pos);
6028        }
6029
6030        function parseThrowStatement(): ThrowStatement {
6031            // ThrowStatement[Yield] :
6032            //      throw [no LineTerminator here]Expression[In, ?Yield];
6033
6034            const pos = getNodePos();
6035            parseExpected(SyntaxKind.ThrowKeyword);
6036
6037            // Because of automatic semicolon insertion, we need to report error if this
6038            // throw could be terminated with a semicolon.  Note: we can't call 'parseExpression'
6039            // directly as that might consume an expression on the following line.
6040            // Instead, we create a "missing" identifier, but don't report an error. The actual error
6041            // will be reported in the grammar walker.
6042            let expression = scanner.hasPrecedingLineBreak() ? undefined : allowInAnd(parseExpression);
6043            if (expression === undefined) {
6044                identifierCount++;
6045                expression = finishNode(factory.createIdentifier(""), getNodePos());
6046            }
6047            parseSemicolon();
6048            return finishNode(factory.createThrowStatement(expression), pos);
6049        }
6050
6051        // TODO: Review for error recovery
6052        function parseTryStatement(): TryStatement {
6053            const pos = getNodePos();
6054
6055            parseExpected(SyntaxKind.TryKeyword);
6056            const tryBlock = parseBlock(/*ignoreMissingOpenBrace*/ false);
6057            const catchClause = token() === SyntaxKind.CatchKeyword ? parseCatchClause() : undefined;
6058
6059            // If we don't have a catch clause, then we must have a finally clause.  Try to parse
6060            // one out no matter what.
6061            let finallyBlock: Block | undefined;
6062            if (!catchClause || token() === SyntaxKind.FinallyKeyword) {
6063                parseExpected(SyntaxKind.FinallyKeyword);
6064                finallyBlock = parseBlock(/*ignoreMissingOpenBrace*/ false);
6065            }
6066
6067            return finishNode(factory.createTryStatement(tryBlock, catchClause, finallyBlock), pos);
6068        }
6069
6070        function parseCatchClause(): CatchClause {
6071            const pos = getNodePos();
6072            parseExpected(SyntaxKind.CatchKeyword);
6073
6074            let variableDeclaration;
6075            if (parseOptional(SyntaxKind.OpenParenToken)) {
6076                variableDeclaration = parseVariableDeclaration();
6077                parseExpected(SyntaxKind.CloseParenToken);
6078            }
6079            else {
6080                // Keep shape of node to avoid degrading performance.
6081                variableDeclaration = undefined;
6082            }
6083
6084            const block = parseBlock(/*ignoreMissingOpenBrace*/ false);
6085            return finishNode(factory.createCatchClause(variableDeclaration, block), pos);
6086        }
6087
6088        function parseDebuggerStatement(): Statement {
6089            const pos = getNodePos();
6090            parseExpected(SyntaxKind.DebuggerKeyword);
6091            parseSemicolon();
6092            return finishNode(factory.createDebuggerStatement(), pos);
6093        }
6094
6095        function parseExpressionOrLabeledStatement(): ExpressionStatement | LabeledStatement {
6096            // Avoiding having to do the lookahead for a labeled statement by just trying to parse
6097            // out an expression, seeing if it is identifier and then seeing if it is followed by
6098            // a colon.
6099            const pos = getNodePos();
6100            let hasJSDoc = hasPrecedingJSDocComment();
6101            let node: ExpressionStatement | LabeledStatement;
6102            const hasParen = token() === SyntaxKind.OpenParenToken;
6103            const expression = allowInAnd(parseExpression);
6104            if (ts.isIdentifier(expression) && parseOptional(SyntaxKind.ColonToken)) {
6105                node = factory.createLabeledStatement(expression, parseStatement());
6106            }
6107            else {
6108                parseSemicolon();
6109                node = factory.createExpressionStatement(expression);
6110                if (hasParen) {
6111                    // do not parse the same jsdoc twice
6112                    hasJSDoc = false;
6113                }
6114            }
6115            return withJSDoc(finishNode(node, pos), hasJSDoc);
6116        }
6117
6118        function nextTokenIsIdentifierOrKeywordOnSameLine() {
6119            nextToken();
6120            return tokenIsIdentifierOrKeyword(token()) && !scanner.hasPrecedingLineBreak();
6121        }
6122
6123        function nextTokenIsClassKeywordOnSameLine() {
6124            nextToken();
6125            return token() === SyntaxKind.ClassKeyword && !scanner.hasPrecedingLineBreak();
6126        }
6127
6128        function nextTokenIsFunctionKeywordOnSameLine() {
6129            nextToken();
6130            return token() === SyntaxKind.FunctionKeyword && !scanner.hasPrecedingLineBreak();
6131        }
6132
6133        function nextTokenIsIdentifierOrKeywordOrLiteralOnSameLine() {
6134            nextToken();
6135            return (tokenIsIdentifierOrKeyword(token()) || token() === SyntaxKind.NumericLiteral || token() === SyntaxKind.BigIntLiteral || token() === SyntaxKind.StringLiteral) && !scanner.hasPrecedingLineBreak();
6136        }
6137
6138        function isDeclaration(): boolean {
6139            while (true) {
6140                switch (token()) {
6141                    case SyntaxKind.VarKeyword:
6142                    case SyntaxKind.LetKeyword:
6143                    case SyntaxKind.ConstKeyword:
6144                    case SyntaxKind.FunctionKeyword:
6145                    case SyntaxKind.ClassKeyword:
6146                    case SyntaxKind.EnumKeyword:
6147                        return true;
6148                    case SyntaxKind.StructKeyword:
6149                        return inEtsContext();
6150
6151
6152                    // 'declare', 'module', 'namespace', 'interface'* and 'type' are all legal JavaScript identifiers;
6153                    // however, an identifier cannot be followed by another identifier on the same line. This is what we
6154                    // count on to parse out the respective declarations. For instance, we exploit this to say that
6155                    //
6156                    //    namespace n
6157                    //
6158                    // can be none other than the beginning of a namespace declaration, but need to respect that JavaScript sees
6159                    //
6160                    //    namespace
6161                    //    n
6162                    //
6163                    // as the identifier 'namespace' on one line followed by the identifier 'n' on another.
6164                    // We need to look one token ahead to see if it permissible to try parsing a declaration.
6165                    //
6166                    // *Note*: 'interface' is actually a strict mode reserved word. So while
6167                    //
6168                    //   "use strict"
6169                    //   interface
6170                    //   I {}
6171                    //
6172                    // could be legal, it would add complexity for very little gain.
6173                    case SyntaxKind.InterfaceKeyword:
6174                    case SyntaxKind.TypeKeyword:
6175                        return nextTokenIsIdentifierOnSameLine();
6176                    case SyntaxKind.ModuleKeyword:
6177                    case SyntaxKind.NamespaceKeyword:
6178                        return nextTokenIsIdentifierOrStringLiteralOnSameLine();
6179                    case SyntaxKind.AbstractKeyword:
6180                    case SyntaxKind.AsyncKeyword:
6181                    case SyntaxKind.DeclareKeyword:
6182                    case SyntaxKind.PrivateKeyword:
6183                    case SyntaxKind.ProtectedKeyword:
6184                    case SyntaxKind.PublicKeyword:
6185                    case SyntaxKind.ReadonlyKeyword:
6186                        nextToken();
6187                        // ASI takes effect for this modifier.
6188                        if (scanner.hasPrecedingLineBreak()) {
6189                            return false;
6190                        }
6191                        continue;
6192
6193                    case SyntaxKind.GlobalKeyword:
6194                        nextToken();
6195                        return token() === SyntaxKind.OpenBraceToken || token() === SyntaxKind.Identifier || token() === SyntaxKind.ExportKeyword;
6196
6197                    case SyntaxKind.ImportKeyword:
6198                        nextToken();
6199                        return token() === SyntaxKind.StringLiteral || token() === SyntaxKind.AsteriskToken ||
6200                            token() === SyntaxKind.OpenBraceToken || tokenIsIdentifierOrKeyword(token());
6201                    case SyntaxKind.ExportKeyword:
6202                        let currentToken = nextToken();
6203                        if (currentToken === SyntaxKind.TypeKeyword) {
6204                            currentToken = lookAhead(nextToken);
6205                        }
6206                        if (currentToken === SyntaxKind.EqualsToken || currentToken === SyntaxKind.AsteriskToken ||
6207                            currentToken === SyntaxKind.OpenBraceToken || currentToken === SyntaxKind.DefaultKeyword ||
6208                            currentToken === SyntaxKind.AsKeyword) {
6209                            return true;
6210                        }
6211                        continue;
6212
6213                    case SyntaxKind.StaticKeyword:
6214                        nextToken();
6215                        continue;
6216                    default:
6217                        return false;
6218                }
6219            }
6220        }
6221
6222        function isStartOfDeclaration(): boolean {
6223            return lookAhead(isDeclaration);
6224        }
6225
6226        function isStartOfStatement(): boolean {
6227            switch (token()) {
6228                case SyntaxKind.AtToken:
6229                case SyntaxKind.SemicolonToken:
6230                case SyntaxKind.OpenBraceToken:
6231                case SyntaxKind.VarKeyword:
6232                case SyntaxKind.LetKeyword:
6233                case SyntaxKind.FunctionKeyword:
6234                case SyntaxKind.ClassKeyword:
6235                case SyntaxKind.EnumKeyword:
6236                case SyntaxKind.IfKeyword:
6237                case SyntaxKind.DoKeyword:
6238                case SyntaxKind.WhileKeyword:
6239                case SyntaxKind.ForKeyword:
6240                case SyntaxKind.ContinueKeyword:
6241                case SyntaxKind.BreakKeyword:
6242                case SyntaxKind.ReturnKeyword:
6243                case SyntaxKind.WithKeyword:
6244                case SyntaxKind.SwitchKeyword:
6245                case SyntaxKind.ThrowKeyword:
6246                case SyntaxKind.TryKeyword:
6247                case SyntaxKind.DebuggerKeyword:
6248                // 'catch' and 'finally' do not actually indicate that the code is part of a statement,
6249                // however, we say they are here so that we may gracefully parse them and error later.
6250                // falls through
6251                case SyntaxKind.CatchKeyword:
6252                case SyntaxKind.FinallyKeyword:
6253                    return true;
6254                case SyntaxKind.StructKeyword:
6255                    return inEtsContext();
6256
6257                case SyntaxKind.ImportKeyword:
6258                    return isStartOfDeclaration() || lookAhead(nextTokenIsOpenParenOrLessThanOrDot);
6259
6260                case SyntaxKind.ConstKeyword:
6261                case SyntaxKind.ExportKeyword:
6262                    return isStartOfDeclaration();
6263
6264                case SyntaxKind.AsyncKeyword:
6265                case SyntaxKind.DeclareKeyword:
6266                case SyntaxKind.InterfaceKeyword:
6267                case SyntaxKind.ModuleKeyword:
6268                case SyntaxKind.NamespaceKeyword:
6269                case SyntaxKind.TypeKeyword:
6270                case SyntaxKind.GlobalKeyword:
6271                    // When these don't start a declaration, they're an identifier in an expression statement
6272                    return true;
6273
6274                case SyntaxKind.PublicKeyword:
6275                case SyntaxKind.PrivateKeyword:
6276                case SyntaxKind.ProtectedKeyword:
6277                case SyntaxKind.StaticKeyword:
6278                case SyntaxKind.ReadonlyKeyword:
6279                    // When these don't start a declaration, they may be the start of a class member if an identifier
6280                    // immediately follows. Otherwise they're an identifier in an expression statement.
6281                    return isStartOfDeclaration() || !lookAhead(nextTokenIsIdentifierOrKeywordOnSameLine);
6282
6283                default:
6284                    return isStartOfExpression();
6285            }
6286        }
6287
6288        function nextTokenIsIdentifierOrStartOfDestructuring() {
6289            nextToken();
6290            return isIdentifier() || token() === SyntaxKind.OpenBraceToken || token() === SyntaxKind.OpenBracketToken;
6291        }
6292
6293        function isLetDeclaration() {
6294            // In ES6 'let' always starts a lexical declaration if followed by an identifier or {
6295            // or [.
6296            return lookAhead(nextTokenIsIdentifierOrStartOfDestructuring);
6297        }
6298
6299        function parseStatement(): Statement {
6300            switch (token()) {
6301                case SyntaxKind.SemicolonToken:
6302                    return parseEmptyStatement();
6303                case SyntaxKind.OpenBraceToken:
6304                    return parseBlock(/*ignoreMissingOpenBrace*/ false);
6305                case SyntaxKind.VarKeyword:
6306                    return parseVariableStatement(getNodePos(), hasPrecedingJSDocComment(), /*decorators*/ undefined, /*modifiers*/ undefined);
6307                case SyntaxKind.LetKeyword:
6308                    if (isLetDeclaration()) {
6309                        return parseVariableStatement(getNodePos(), hasPrecedingJSDocComment(), /*decorators*/ undefined, /*modifiers*/ undefined);
6310                    }
6311                    break;
6312                case SyntaxKind.FunctionKeyword:
6313                    return parseFunctionDeclaration(getNodePos(), hasPrecedingJSDocComment(), /*decorators*/ undefined, /*modifiers*/ undefined);
6314                case SyntaxKind.StructKeyword:
6315                    if (inEtsContext()) {
6316                        return parseStructDeclaration(getNodePos(), hasPrecedingJSDocComment(), /*decorators*/ undefined, /*modifiers*/ undefined);
6317                    }
6318                    break;
6319                case SyntaxKind.ClassKeyword:
6320                    return parseClassDeclaration(getNodePos(), hasPrecedingJSDocComment(), /*decorators*/ undefined, /*modifiers*/ undefined);
6321                case SyntaxKind.IfKeyword:
6322                    return parseIfStatement();
6323                case SyntaxKind.DoKeyword:
6324                    return parseDoStatement();
6325                case SyntaxKind.WhileKeyword:
6326                    return parseWhileStatement();
6327                case SyntaxKind.ForKeyword:
6328                    return parseForOrForInOrForOfStatement();
6329                case SyntaxKind.ContinueKeyword:
6330                    return parseBreakOrContinueStatement(SyntaxKind.ContinueStatement);
6331                case SyntaxKind.BreakKeyword:
6332                    return parseBreakOrContinueStatement(SyntaxKind.BreakStatement);
6333                case SyntaxKind.ReturnKeyword:
6334                    return parseReturnStatement();
6335                case SyntaxKind.WithKeyword:
6336                    return parseWithStatement();
6337                case SyntaxKind.SwitchKeyword:
6338                    return parseSwitchStatement();
6339                case SyntaxKind.ThrowKeyword:
6340                    return parseThrowStatement();
6341                case SyntaxKind.TryKeyword:
6342                // Include 'catch' and 'finally' for error recovery.
6343                // falls through
6344                case SyntaxKind.CatchKeyword:
6345                case SyntaxKind.FinallyKeyword:
6346                    return parseTryStatement();
6347                case SyntaxKind.DebuggerKeyword:
6348                    return parseDebuggerStatement();
6349                case SyntaxKind.AtToken:
6350                    return parseDeclaration();
6351                case SyntaxKind.AsyncKeyword:
6352                case SyntaxKind.InterfaceKeyword:
6353                case SyntaxKind.TypeKeyword:
6354                case SyntaxKind.ModuleKeyword:
6355                case SyntaxKind.NamespaceKeyword:
6356                case SyntaxKind.DeclareKeyword:
6357                case SyntaxKind.ConstKeyword:
6358                case SyntaxKind.EnumKeyword:
6359                case SyntaxKind.ExportKeyword:
6360                case SyntaxKind.ImportKeyword:
6361                case SyntaxKind.PrivateKeyword:
6362                case SyntaxKind.ProtectedKeyword:
6363                case SyntaxKind.PublicKeyword:
6364                case SyntaxKind.AbstractKeyword:
6365                case SyntaxKind.StaticKeyword:
6366                case SyntaxKind.ReadonlyKeyword:
6367                case SyntaxKind.GlobalKeyword:
6368                    if (isStartOfDeclaration()) {
6369                        return parseDeclaration();
6370                    }
6371                    break;
6372            }
6373            return parseExpressionOrLabeledStatement();
6374        }
6375
6376        function isDeclareModifier(modifier: Modifier) {
6377            return modifier.kind === SyntaxKind.DeclareKeyword;
6378        }
6379
6380        function parseDeclaration(): Statement {
6381            // TODO: Can we hold onto the parsed decorators/modifiers and advance the scanner
6382            //       if we can't reuse the declaration, so that we don't do this work twice?
6383            //
6384            // `parseListElement` attempted to get the reused node at this position,
6385            // but the ambient context flag was not yet set, so the node appeared
6386            // not reusable in that context.
6387            const isAmbient = some(lookAhead(() => (parseDecorators(), parseModifiers())), isDeclareModifier);
6388            if (isAmbient) {
6389                const node = tryReuseAmbientDeclaration();
6390                if (node) {
6391                    return node;
6392                }
6393            }
6394
6395            const pos = getNodePos();
6396            const hasJSDoc = hasPrecedingJSDocComment();
6397            const decorators = parseDecorators();
6398
6399            if (token() === SyntaxKind.FunctionKeyword || token() === SyntaxKind.ExportKeyword) {
6400                if (hasEtsExtendDecoratorNames(decorators, sourceFileCompilerOptions)) {
6401                    const extendEtsComponentDecoratorNames = getEtsExtendDecoratorComponentNames(decorators, sourceFileCompilerOptions);
6402                    if (extendEtsComponentDecoratorNames.length > 0) {
6403                        sourceFileCompilerOptions.ets?.extend.components.forEach(({ name, type, instance }) => {
6404                            if (name === last(extendEtsComponentDecoratorNames)) {
6405                                extendEtsComponentDeclaration = { name, type, instance };
6406                            }
6407                        });
6408                    }
6409                    setEtsExtendComponentsContext(!!extendEtsComponentDeclaration);
6410                }
6411                else if (hasEtsStylesDecoratorNames(decorators, sourceFileCompilerOptions)) {
6412                    const stylesEtsComponentDecoratorNames = getEtsStylesDecoratorComponentNames(decorators, sourceFileCompilerOptions);
6413                    if (stylesEtsComponentDecoratorNames.length > 0) {
6414                        stylesEtsComponentDeclaration = sourceFileCompilerOptions.ets?.styles.component;
6415                    }
6416                    setEtsStylesComponentsContext(!!stylesEtsComponentDeclaration);
6417                }
6418                else {
6419                    setEtsComponentsContext(isTokenInsideBuilder(decorators, sourceFileCompilerOptions));
6420                }
6421            }
6422
6423            const modifiers = parseModifiers();
6424            if (isAmbient) {
6425                for (const m of modifiers!) {
6426                    (m as Mutable<Node>).flags |= NodeFlags.Ambient;
6427                }
6428                return doInsideOfContext(NodeFlags.Ambient, () => parseDeclarationWorker(pos, hasJSDoc, decorators, modifiers));
6429            }
6430            else {
6431                return parseDeclarationWorker(pos, hasJSDoc, decorators, modifiers);
6432            }
6433        }
6434
6435        function tryReuseAmbientDeclaration(): Statement | undefined {
6436            return doInsideOfContext(NodeFlags.Ambient, () => {
6437                const node = currentNode(parsingContext);
6438                if (node) {
6439                    return consumeNode(node) as Statement;
6440                }
6441            });
6442        }
6443
6444        function parseDeclarationWorker(pos: number, hasJSDoc: boolean, decorators: NodeArray<Decorator> | undefined, modifiers: NodeArray<Modifier> | undefined): Statement {
6445            switch (token()) {
6446                case SyntaxKind.VarKeyword:
6447                case SyntaxKind.LetKeyword:
6448                case SyntaxKind.ConstKeyword:
6449                    return parseVariableStatement(pos, hasJSDoc, decorators, modifiers);
6450                case SyntaxKind.FunctionKeyword:
6451                    return parseFunctionDeclaration(pos, hasJSDoc, decorators, modifiers);
6452                case SyntaxKind.ClassKeyword:
6453                    return parseClassDeclaration(pos, hasJSDoc, decorators, modifiers);
6454                case SyntaxKind.StructKeyword:
6455                    if (inEtsContext()) {
6456                        return parseStructDeclaration(pos, hasJSDoc, decorators, modifiers);
6457                    }
6458                    return parseDeclarationDefault(pos,decorators, modifiers);
6459                case SyntaxKind.InterfaceKeyword:
6460                    return parseInterfaceDeclaration(pos, hasJSDoc, decorators, modifiers);
6461                case SyntaxKind.TypeKeyword:
6462                    return parseTypeAliasDeclaration(pos, hasJSDoc, decorators, modifiers);
6463                case SyntaxKind.EnumKeyword:
6464                    return parseEnumDeclaration(pos, hasJSDoc, decorators, modifiers);
6465                case SyntaxKind.GlobalKeyword:
6466                case SyntaxKind.ModuleKeyword:
6467                case SyntaxKind.NamespaceKeyword:
6468                    return parseModuleDeclaration(pos, hasJSDoc, decorators, modifiers);
6469                case SyntaxKind.ImportKeyword:
6470                    return parseImportDeclarationOrImportEqualsDeclaration(pos, hasJSDoc, decorators, modifiers);
6471                case SyntaxKind.ExportKeyword:
6472                    nextToken();
6473                    switch (token()) {
6474                        case SyntaxKind.DefaultKeyword:
6475                        case SyntaxKind.EqualsToken:
6476                            return parseExportAssignment(pos, hasJSDoc, decorators, modifiers);
6477                        case SyntaxKind.AsKeyword:
6478                            return parseNamespaceExportDeclaration(pos, hasJSDoc, decorators, modifiers);
6479                        default:
6480                            return parseExportDeclaration(pos, hasJSDoc, decorators, modifiers);
6481                    }
6482                default:
6483                    return parseDeclarationDefault(pos,decorators, modifiers);
6484            }
6485        }
6486
6487        function parseDeclarationDefault(pos: number,decorators: NodeArray<Decorator> | undefined, modifiers: NodeArray<Modifier> | undefined): Statement {
6488            if (decorators || modifiers) {
6489                // We reached this point because we encountered decorators and/or modifiers and assumed a declaration
6490                // would follow. For recovery and error reporting purposes, return an incomplete declaration.
6491                const missing = createMissingNode<MissingDeclaration>(SyntaxKind.MissingDeclaration, /*reportAtCurrentPosition*/ true, Diagnostics.Declaration_expected);
6492                setTextRangePos(missing, pos);
6493                missing.decorators = decorators;
6494                missing.modifiers = modifiers;
6495                return missing;
6496            }
6497            return undefined!; // TODO: GH#18217
6498        }
6499
6500        function nextTokenIsIdentifierOrStringLiteralOnSameLine() {
6501            nextToken();
6502            return !scanner.hasPrecedingLineBreak() && (isIdentifier() || token() === SyntaxKind.StringLiteral);
6503        }
6504
6505        function parseFunctionBlockOrSemicolon(flags: SignatureFlags, diagnosticMessage?: DiagnosticMessage): Block | undefined {
6506            if (token() !== SyntaxKind.OpenBraceToken && canParseSemicolon()) {
6507                parseSemicolon();
6508                return;
6509            }
6510
6511            return parseFunctionBlock(flags, diagnosticMessage);
6512        }
6513
6514        // DECLARATIONS
6515
6516        function parseArrayBindingElement(): ArrayBindingElement {
6517            const pos = getNodePos();
6518            if (token() === SyntaxKind.CommaToken) {
6519                return finishNode(factory.createOmittedExpression(), pos);
6520            }
6521            const dotDotDotToken = parseOptionalToken(SyntaxKind.DotDotDotToken);
6522            const name = parseIdentifierOrPattern();
6523            const initializer = parseInitializer();
6524            return finishNode(factory.createBindingElement(dotDotDotToken, /*propertyName*/ undefined, name, initializer), pos);
6525        }
6526
6527        function parseObjectBindingElement(): BindingElement {
6528            const pos = getNodePos();
6529            const dotDotDotToken = parseOptionalToken(SyntaxKind.DotDotDotToken);
6530            const tokenIsIdentifier = isBindingIdentifier();
6531            let propertyName: PropertyName | undefined = parsePropertyName();
6532            let name: BindingName;
6533            if (tokenIsIdentifier && token() !== SyntaxKind.ColonToken) {
6534                name = <Identifier>propertyName;
6535                propertyName = undefined;
6536            }
6537            else {
6538                parseExpected(SyntaxKind.ColonToken);
6539                name = parseIdentifierOrPattern();
6540            }
6541            const initializer = parseInitializer();
6542            return finishNode(factory.createBindingElement(dotDotDotToken, propertyName, name, initializer), pos);
6543        }
6544
6545        function parseObjectBindingPattern(): ObjectBindingPattern {
6546            const pos = getNodePos();
6547            parseExpected(SyntaxKind.OpenBraceToken);
6548            const elements = parseDelimitedList(ParsingContext.ObjectBindingElements, parseObjectBindingElement);
6549            parseExpected(SyntaxKind.CloseBraceToken);
6550            return finishNode(factory.createObjectBindingPattern(elements), pos);
6551        }
6552
6553        function parseArrayBindingPattern(): ArrayBindingPattern {
6554            const pos = getNodePos();
6555            parseExpected(SyntaxKind.OpenBracketToken);
6556            const elements = parseDelimitedList(ParsingContext.ArrayBindingElements, parseArrayBindingElement);
6557            parseExpected(SyntaxKind.CloseBracketToken);
6558            return finishNode(factory.createArrayBindingPattern(elements), pos);
6559        }
6560
6561        function isBindingIdentifierOrPrivateIdentifierOrPattern() {
6562            return token() === SyntaxKind.OpenBraceToken
6563                || token() === SyntaxKind.OpenBracketToken
6564                || token() === SyntaxKind.PrivateIdentifier
6565                || isBindingIdentifier();
6566        }
6567
6568        function parseIdentifierOrPattern(privateIdentifierDiagnosticMessage?: DiagnosticMessage): Identifier | BindingPattern {
6569            if (token() === SyntaxKind.OpenBracketToken) {
6570                return parseArrayBindingPattern();
6571            }
6572            if (token() === SyntaxKind.OpenBraceToken) {
6573                return parseObjectBindingPattern();
6574            }
6575            return parseBindingIdentifier(privateIdentifierDiagnosticMessage);
6576        }
6577
6578        function parseVariableDeclarationAllowExclamation() {
6579            return parseVariableDeclaration(/*allowExclamation*/ true);
6580        }
6581
6582        function parseVariableDeclaration(allowExclamation?: boolean): VariableDeclaration {
6583            const pos = getNodePos();
6584            const name = parseIdentifierOrPattern(Diagnostics.Private_identifiers_are_not_allowed_in_variable_declarations);
6585            let exclamationToken: ExclamationToken | undefined;
6586            if (allowExclamation && name.kind === SyntaxKind.Identifier &&
6587                token() === SyntaxKind.ExclamationToken && !scanner.hasPrecedingLineBreak()) {
6588                exclamationToken = parseTokenNode<Token<SyntaxKind.ExclamationToken>>();
6589            }
6590            const type = parseTypeAnnotation();
6591            const initializer = isInOrOfKeyword(token()) ? undefined : parseInitializer();
6592            const node = factory.createVariableDeclaration(name, exclamationToken, type, initializer);
6593            return finishNode(node, pos);
6594        }
6595
6596        function parseVariableDeclarationList(inForStatementInitializer: boolean): VariableDeclarationList {
6597            const pos = getNodePos();
6598
6599            let flags: NodeFlags = 0;
6600            switch (token()) {
6601                case SyntaxKind.VarKeyword:
6602                    break;
6603                case SyntaxKind.LetKeyword:
6604                    flags |= NodeFlags.Let;
6605                    break;
6606                case SyntaxKind.ConstKeyword:
6607                    flags |= NodeFlags.Const;
6608                    break;
6609                default:
6610                    Debug.fail();
6611            }
6612
6613            nextToken();
6614
6615            // The user may have written the following:
6616            //
6617            //    for (let of X) { }
6618            //
6619            // In this case, we want to parse an empty declaration list, and then parse 'of'
6620            // as a keyword. The reason this is not automatic is that 'of' is a valid identifier.
6621            // So we need to look ahead to determine if 'of' should be treated as a keyword in
6622            // this context.
6623            // The checker will then give an error that there is an empty declaration list.
6624            let declarations;
6625            if (token() === SyntaxKind.OfKeyword && lookAhead(canFollowContextualOfKeyword)) {
6626                declarations = createMissingList<VariableDeclaration>();
6627            }
6628            else {
6629                const savedDisallowIn = inDisallowInContext();
6630                setDisallowInContext(inForStatementInitializer);
6631
6632                declarations = parseDelimitedList(ParsingContext.VariableDeclarations,
6633                    inForStatementInitializer ? parseVariableDeclaration : parseVariableDeclarationAllowExclamation);
6634
6635                setDisallowInContext(savedDisallowIn);
6636            }
6637
6638            return finishNode(factory.createVariableDeclarationList(declarations, flags), pos);
6639        }
6640
6641        function canFollowContextualOfKeyword(): boolean {
6642            return nextTokenIsIdentifier() && nextToken() === SyntaxKind.CloseParenToken;
6643        }
6644
6645        function parseVariableStatement(pos: number, hasJSDoc: boolean, decorators: NodeArray<Decorator> | undefined, modifiers: NodeArray<Modifier> | undefined): VariableStatement {
6646            const declarationList = parseVariableDeclarationList(/*inForStatementInitializer*/ false);
6647            parseSemicolon();
6648            const node = factory.createVariableStatement(modifiers, declarationList);
6649            // Decorators are not allowed on a variable statement, so we keep track of them to report them in the grammar checker.
6650            node.decorators = decorators;
6651            return withJSDoc(finishNode(node, pos), hasJSDoc);
6652        }
6653
6654        function parseFunctionDeclaration(pos: number, hasJSDoc: boolean, decorators: NodeArray<Decorator> | undefined, modifiers: NodeArray<Modifier> | undefined): FunctionDeclaration {
6655            const savedAwaitContext = inAwaitContext();
6656            const modifierFlags = modifiersToFlags(modifiers);
6657            parseExpected(SyntaxKind.FunctionKeyword);
6658            const asteriskToken = parseOptionalToken(SyntaxKind.AsteriskToken);
6659            // We don't parse the name here in await context, instead we will report a grammar error in the checker.
6660            const name = modifierFlags & ModifierFlags.Default ? parseOptionalBindingIdentifier() : parseBindingIdentifier();
6661            if(name && hasEtsStylesDecoratorNames(decorators, sourceFileCompilerOptions)) {
6662                fileStylesComponents.set(name.escapedText.toString(), SyntaxKind.FunctionDeclaration);
6663            }
6664            setEtsBuilderContext(hasEtsBuilderDecoratorNames(decorators, sourceFileCompilerOptions));
6665            const isGenerator = asteriskToken ? SignatureFlags.Yield : SignatureFlags.None;
6666            const isAsync = modifierFlags & ModifierFlags.Async ? SignatureFlags.Await : SignatureFlags.None;
6667            const typeParameters = inEtsStylesComponentsContext() && stylesEtsComponentDeclaration ? parseEtsTypeParameters(scanner.getStartPos()) : parseTypeParameters();
6668            if (modifierFlags & ModifierFlags.Export) setAwaitContext(/*value*/ true);
6669            const parameters = parseParameters(isGenerator | isAsync);
6670            const typeStartPos = scanner.getStartPos();
6671            const type = getFunctionDeclarationReturnType();
6672            const body = parseFunctionBlockOrSemicolon(isGenerator | isAsync, Diagnostics.or_expected);
6673            setEtsBuilderContext(false);
6674            setEtsExtendComponentsContext(false);
6675            extendEtsComponentDeclaration = undefined;
6676            setEtsStylesComponentsContext(false);
6677            stylesEtsComponentDeclaration = undefined;
6678            setEtsComponentsContext(inBuildContext());
6679            setAwaitContext(savedAwaitContext);
6680            const node = factory.createFunctionDeclaration(decorators, modifiers, asteriskToken, name, typeParameters, parameters, type, body);
6681            return withJSDoc(finishNode(node, pos), hasJSDoc);
6682
6683            function getFunctionDeclarationReturnType(): TypeNode | undefined {
6684                let returnType = parseReturnType(SyntaxKind.ColonToken, /*isType*/ false);
6685                // If function decorated by Extend and type is not defined, then will use Ets Extend Components Type
6686                if (!returnType && extendEtsComponentDeclaration && inEtsExtendComponentsContext()) {
6687                    returnType = finishVirtualNode(factory.createTypeReferenceNode(
6688                        finishVirtualNode(factory.createIdentifier(extendEtsComponentDeclaration.type), typeStartPos, typeStartPos)),
6689                        typeStartPos, typeStartPos);
6690                }
6691                // If function decorated by Styles and type is not defined, then will use Ets Styles Components Type
6692                if (!returnType && stylesEtsComponentDeclaration && inEtsStylesComponentsContext()) {
6693                    returnType = finishVirtualNode(factory.createTypeReferenceNode(
6694                        finishVirtualNode(factory.createIdentifier(stylesEtsComponentDeclaration.type), typeStartPos, typeStartPos)),
6695                        typeStartPos, typeStartPos);
6696                }
6697                return returnType;
6698            }
6699        }
6700
6701        function parseConstructorName() {
6702            if (token() === SyntaxKind.ConstructorKeyword) {
6703                return parseExpected(SyntaxKind.ConstructorKeyword);
6704            }
6705            if (token() === SyntaxKind.StringLiteral && lookAhead(nextToken) === SyntaxKind.OpenParenToken) {
6706                return tryParse(() => {
6707                    const literalNode = parseLiteralNode();
6708                    return literalNode.text === "constructor" ? literalNode : undefined;
6709                });
6710            }
6711        }
6712
6713        function tryParseConstructorDeclaration(pos: number, hasJSDoc: boolean, decorators: NodeArray<Decorator> | undefined, modifiers: NodeArray<Modifier> | undefined): ConstructorDeclaration | undefined {
6714            return tryParse(() => {
6715                if (parseConstructorName()) {
6716                    const typeParameters = parseTypeParameters();
6717                    const parameters = parseParameters(SignatureFlags.None);
6718                    const type = parseReturnType(SyntaxKind.ColonToken, /*isType*/ false);
6719                    const body = parseFunctionBlockOrSemicolon(SignatureFlags.None, Diagnostics.or_expected);
6720                    const node = factory.createConstructorDeclaration(decorators, modifiers, parameters, body);
6721                    // Attach `typeParameters` and `type` if they exist so that we can report them in the grammar checker.
6722                    node.typeParameters = typeParameters;
6723                    node.type = type;
6724                    return withJSDoc(finishNode(node, pos), hasJSDoc);
6725                }
6726            });
6727        }
6728
6729
6730        function isTokenInsideStructBuild(methodName: PropertyName): boolean {
6731            const renderMethod = sourceFileCompilerOptions.ets?.render?.method?.find(render => render === "build") ?? "build";
6732
6733            if (methodName.kind === SyntaxKind.Identifier && methodName.escapedText === renderMethod) {
6734                return true;
6735            }
6736            return false;
6737        }
6738
6739        function isTokenInsideStructBuilder(decorators: NodeArray<Decorator> | undefined): boolean {
6740            return isTokenInsideBuilder(decorators, sourceFileCompilerOptions);
6741        }
6742
6743        function isTokenInsideStructPageTransition(methodName: PropertyName): boolean {
6744            const renderMethod = sourceFileCompilerOptions.ets?.render?.method?.find(render => render === "pageTransition") ?? "pageTransition";
6745
6746            if (methodName.kind === SyntaxKind.Identifier && methodName.escapedText === renderMethod) {
6747                return true;
6748            }
6749            return false;
6750        }
6751
6752        function parseMethodDeclaration(
6753            pos: number,
6754            hasJSDoc: boolean,
6755            decorators: NodeArray<Decorator> | undefined,
6756            modifiers: NodeArray<Modifier> | undefined,
6757            asteriskToken: AsteriskToken | undefined,
6758            name: PropertyName,
6759            questionToken: QuestionToken | undefined,
6760            exclamationToken: ExclamationToken | undefined,
6761            diagnosticMessage?: DiagnosticMessage
6762        ): MethodDeclaration {
6763            const methodName = getPropertyNameForPropertyNameNode(name)?.toString();
6764            setEtsBuildContext(methodName === sourceFileCompilerOptions?.ets?.render?.method?.find(render => render === "build"));
6765            setEtsBuilderContext(hasEtsBuilderDecoratorNames(decorators, sourceFileCompilerOptions));
6766            if (inStructContext() && hasEtsStylesDecoratorNames(decorators, sourceFileCompilerOptions)) {
6767                if (methodName && currentStructName) {
6768                    structStylesComponents.set(methodName, { structName: currentStructName, kind: SyntaxKind.MethodDeclaration });
6769                }
6770                const stylesEtsComponentDecoratorNames = getEtsStylesDecoratorComponentNames(decorators, sourceFileCompilerOptions);
6771                if (stylesEtsComponentDecoratorNames.length > 0) {
6772                    stylesEtsComponentDeclaration = sourceFileCompilerOptions.ets?.styles.component;
6773                }
6774                setEtsStylesComponentsContext(!!stylesEtsComponentDeclaration);
6775            }
6776            setEtsComponentsContext(inStructContext() && (isTokenInsideStructBuild(name) || isTokenInsideStructBuilder(decorators) ||
6777                isTokenInsideStructPageTransition(name)));
6778            const isGenerator = asteriskToken ? SignatureFlags.Yield : SignatureFlags.None;
6779            const isAsync = some(modifiers, isAsyncModifier) ? SignatureFlags.Await : SignatureFlags.None;
6780            const typeParameters = inEtsStylesComponentsContext() && stylesEtsComponentDeclaration ? parseEtsTypeParameters(pos) : parseTypeParameters();
6781            const parameters = parseParameters(isGenerator | isAsync);
6782            const typeStartPos = scanner.getStartPos();
6783            const type = getMethodDeclarationReturnType();
6784            const body = parseFunctionBlockOrSemicolon(isGenerator | isAsync, diagnosticMessage);
6785            const node = factory.createMethodDeclaration(
6786                decorators,
6787                modifiers,
6788                asteriskToken,
6789                name,
6790                questionToken,
6791                typeParameters,
6792                parameters,
6793                type,
6794                body
6795            );
6796            // An exclamation token on a method is invalid syntax and will be handled by the grammar checker
6797            node.exclamationToken = exclamationToken;
6798            setEtsBuildContext(false);
6799            setEtsBuilderContext(false);
6800            setEtsStylesComponentsContext(false);
6801            stylesEtsComponentDeclaration = undefined;
6802            setEtsComponentsContext(false);
6803            return withJSDoc(finishNode(node, pos), hasJSDoc);
6804
6805            function getMethodDeclarationReturnType(): TypeNode | undefined {
6806                let returnType = parseReturnType(SyntaxKind.ColonToken, /*isType*/ false);
6807                // If function decorated by Styles and type is not defined, then will use Ets Styles Components Type
6808                if (!returnType && stylesEtsComponentDeclaration && inEtsStylesComponentsContext()) {
6809                    returnType = finishVirtualNode(factory.createTypeReferenceNode(
6810                        finishVirtualNode(factory.createIdentifier(stylesEtsComponentDeclaration.type), typeStartPos, typeStartPos)),
6811                        typeStartPos, typeStartPos);
6812                }
6813                return returnType;
6814            }
6815        }
6816
6817        function parsePropertyDeclaration(
6818            pos: number,
6819            hasJSDoc: boolean,
6820            decorators: NodeArray<Decorator> | undefined,
6821            modifiers: NodeArray<Modifier> | undefined,
6822            name: PropertyName,
6823            questionToken: QuestionToken | undefined
6824        ): PropertyDeclaration {
6825            const exclamationToken = !questionToken && !scanner.hasPrecedingLineBreak() ? parseOptionalToken(SyntaxKind.ExclamationToken) : undefined;
6826            const type = parseTypeAnnotation();
6827            const initializer = doOutsideOfContext(NodeFlags.YieldContext | NodeFlags.AwaitContext | NodeFlags.DisallowInContext, parseInitializer);
6828            parseSemicolon();
6829            const node = factory.createPropertyDeclaration(decorators, modifiers, name, questionToken || exclamationToken, type, initializer);
6830            return withJSDoc(finishNode(node, pos), hasJSDoc);
6831        }
6832
6833        function parsePropertyOrMethodDeclaration(
6834            pos: number,
6835            hasJSDoc: boolean,
6836            decorators: NodeArray<Decorator> | undefined,
6837            modifiers: NodeArray<Modifier> | undefined
6838        ): PropertyDeclaration | MethodDeclaration {
6839            const asteriskToken = parseOptionalToken(SyntaxKind.AsteriskToken);
6840            const name = parsePropertyName();
6841            // Note: this is not legal as per the grammar.  But we allow it in the parser and
6842            // report an error in the grammar checker.
6843            const questionToken = parseOptionalToken(SyntaxKind.QuestionToken);
6844            if (asteriskToken || token() === SyntaxKind.OpenParenToken || token() === SyntaxKind.LessThanToken) {
6845                return parseMethodDeclaration(pos, hasJSDoc, decorators, modifiers, asteriskToken, name, questionToken, /*exclamationToken*/ undefined, Diagnostics.or_expected);
6846            }
6847            return parsePropertyDeclaration(pos, hasJSDoc, decorators, modifiers, name, questionToken);
6848        }
6849
6850        function parseAccessorDeclaration(pos: number, hasJSDoc: boolean, decorators: NodeArray<Decorator> | undefined, modifiers: NodeArray<Modifier> | undefined, kind: AccessorDeclaration["kind"]): AccessorDeclaration {
6851            const name = parsePropertyName();
6852            const typeParameters = parseTypeParameters();
6853            const parameters = parseParameters(SignatureFlags.None);
6854            const type = parseReturnType(SyntaxKind.ColonToken, /*isType*/ false);
6855            const body = parseFunctionBlockOrSemicolon(SignatureFlags.None);
6856            const node = kind === SyntaxKind.GetAccessor
6857                ? factory.createGetAccessorDeclaration(decorators, modifiers, name, parameters, type, body)
6858                : factory.createSetAccessorDeclaration(decorators, modifiers, name, parameters, body);
6859            // Keep track of `typeParameters` (for both) and `type` (for setters) if they were parsed those indicate grammar errors
6860            node.typeParameters = typeParameters;
6861            if (type && node.kind === SyntaxKind.SetAccessor) (node as Mutable<SetAccessorDeclaration>).type = type;
6862            return withJSDoc(finishNode(node, pos), hasJSDoc);
6863        }
6864
6865        function isClassMemberStart(): boolean {
6866            let idToken: SyntaxKind | undefined;
6867
6868            if (token() === SyntaxKind.AtToken) {
6869                return true;
6870            }
6871
6872            // Eat up all modifiers, but hold on to the last one in case it is actually an identifier.
6873            while (isModifierKind(token())) {
6874                idToken = token();
6875                // If the idToken is a class modifier (protected, private, public, and static), it is
6876                // certain that we are starting to parse class member. This allows better error recovery
6877                // Example:
6878                //      public foo() ...     // true
6879                //      public @dec blah ... // true; we will then report an error later
6880                //      export public ...    // true; we will then report an error later
6881                if (isClassMemberModifier(idToken)) {
6882                    return true;
6883                }
6884
6885                nextToken();
6886            }
6887
6888            if (token() === SyntaxKind.AsteriskToken) {
6889                return true;
6890            }
6891
6892            // Try to get the first property-like token following all modifiers.
6893            // This can either be an identifier or the 'get' or 'set' keywords.
6894            if (isLiteralPropertyName()) {
6895                idToken = token();
6896                nextToken();
6897            }
6898
6899            // Index signatures and computed properties are class members; we can parse.
6900            if (token() === SyntaxKind.OpenBracketToken) {
6901                return true;
6902            }
6903
6904            // If we were able to get any potential identifier...
6905            if (idToken !== undefined) {
6906                // If we have a non-keyword identifier, or if we have an accessor, then it's safe to parse.
6907                if (!isKeyword(idToken) || idToken === SyntaxKind.SetKeyword || idToken === SyntaxKind.GetKeyword) {
6908                    return true;
6909                }
6910
6911                // If it *is* a keyword, but not an accessor, check a little farther along
6912                // to see if it should actually be parsed as a class member.
6913                switch (token()) {
6914                    case SyntaxKind.OpenParenToken:     // Method declaration
6915                    case SyntaxKind.LessThanToken:      // Generic Method declaration
6916                    case SyntaxKind.ExclamationToken:   // Non-null assertion on property name
6917                    case SyntaxKind.ColonToken:         // Type Annotation for declaration
6918                    case SyntaxKind.EqualsToken:        // Initializer for declaration
6919                    case SyntaxKind.QuestionToken:      // Not valid, but permitted so that it gets caught later on.
6920                        return true;
6921                    default:
6922                        // Covers
6923                        //  - Semicolons     (declaration termination)
6924                        //  - Closing braces (end-of-class, must be declaration)
6925                        //  - End-of-files   (not valid, but permitted so that it gets caught later on)
6926                        //  - Line-breaks    (enabling *automatic semicolon insertion*)
6927                        return canParseSemicolon();
6928                }
6929            }
6930
6931            return false;
6932        }
6933
6934        function parseDecoratorExpression() {
6935            if (inAwaitContext() && token() === SyntaxKind.AwaitKeyword) {
6936                // `@await` is is disallowed in an [Await] context, but can cause parsing to go off the rails
6937                // This simply parses the missing identifier and moves on.
6938                const pos = getNodePos();
6939                const awaitExpression = parseIdentifier(Diagnostics.Expression_expected);
6940                nextToken();
6941                const memberExpression = parseMemberExpressionRest(pos, awaitExpression, /*allowOptionalChain*/ true);
6942                return parseCallExpressionRest(pos, memberExpression);
6943            }
6944            return parseLeftHandSideExpressionOrHigher();
6945        }
6946
6947        function tryParseDecorator(): Decorator | undefined {
6948            const pos = getNodePos();
6949            if (!parseOptional(SyntaxKind.AtToken)) {
6950                return undefined;
6951            }
6952            const expression = doInDecoratorContext(parseDecoratorExpression);
6953            return finishNode(factory.createDecorator(expression), pos);
6954        }
6955
6956        function parseDecorators(): NodeArray<Decorator> | undefined {
6957            const pos = getNodePos();
6958            let list, decorator;
6959            while (decorator = tryParseDecorator()) {
6960                list = append(list, decorator);
6961            }
6962            return list && createNodeArray(list, pos);
6963        }
6964
6965        function tryParseModifier(permitInvalidConstAsModifier?: boolean): Modifier | undefined {
6966            const pos = getNodePos();
6967            const kind = token();
6968
6969            if (token() === SyntaxKind.ConstKeyword && permitInvalidConstAsModifier) {
6970                // We need to ensure that any subsequent modifiers appear on the same line
6971                // so that when 'const' is a standalone declaration, we don't issue an error.
6972                if (!tryParse(nextTokenIsOnSameLineAndCanFollowModifier)) {
6973                    return undefined;
6974                }
6975            }
6976            else {
6977                if (!parseAnyContextualModifier()) {
6978                    return undefined;
6979                }
6980            }
6981
6982            return finishNode(factory.createToken(kind as Modifier["kind"]), pos);
6983        }
6984
6985        /*
6986         * There are situations in which a modifier like 'const' will appear unexpectedly, such as on a class member.
6987         * In those situations, if we are entirely sure that 'const' is not valid on its own (such as when ASI takes effect
6988         * and turns it into a standalone declaration), then it is better to parse it and report an error later.
6989         *
6990         * In such situations, 'permitInvalidConstAsModifier' should be set to true.
6991         */
6992        function parseModifiers(permitInvalidConstAsModifier?: boolean): NodeArray<Modifier> | undefined {
6993            const pos = getNodePos();
6994            let list, modifier;
6995            while (modifier = tryParseModifier(permitInvalidConstAsModifier)) {
6996                list = append(list, modifier);
6997            }
6998            return list && createNodeArray(list, pos);
6999        }
7000
7001        function parseModifiersForArrowFunction(): NodeArray<Modifier> | undefined {
7002            let modifiers: NodeArray<Modifier> | undefined;
7003            if (token() === SyntaxKind.AsyncKeyword) {
7004                const pos = getNodePos();
7005                nextToken();
7006                const modifier = finishNode(factory.createToken(SyntaxKind.AsyncKeyword), pos);
7007                modifiers = createNodeArray<Modifier>([modifier], pos);
7008            }
7009            return modifiers;
7010        }
7011
7012        function parseClassElement(): ClassElement {
7013            const pos = getNodePos();
7014            if (token() === SyntaxKind.SemicolonToken) {
7015                nextToken();
7016                return finishNode(factory.createSemicolonClassElement(), pos);
7017            }
7018
7019            const hasJSDoc = hasPrecedingJSDocComment();
7020            const decorators = parseDecorators();
7021            const modifiers = parseModifiers(/*permitInvalidConstAsModifier*/ true);
7022
7023            if (parseContextualModifier(SyntaxKind.GetKeyword)) {
7024                return parseAccessorDeclaration(pos, hasJSDoc, decorators, modifiers, SyntaxKind.GetAccessor);
7025            }
7026
7027            if (parseContextualModifier(SyntaxKind.SetKeyword)) {
7028                return parseAccessorDeclaration(pos, hasJSDoc, decorators, modifiers, SyntaxKind.SetAccessor);
7029            }
7030
7031            if (token() === SyntaxKind.ConstructorKeyword || token() === SyntaxKind.StringLiteral) {
7032                const constructorDeclaration = tryParseConstructorDeclaration(pos, hasJSDoc, decorators, modifiers);
7033                if (constructorDeclaration) {
7034                    return constructorDeclaration;
7035                }
7036            }
7037
7038            if (isIndexSignature()) {
7039                return parseIndexSignatureDeclaration(pos, hasJSDoc, decorators, modifiers);
7040            }
7041
7042            // It is very important that we check this *after* checking indexers because
7043            // the [ token can start an index signature or a computed property name
7044            if (tokenIsIdentifierOrKeyword(token()) ||
7045                token() === SyntaxKind.StringLiteral ||
7046                token() === SyntaxKind.NumericLiteral ||
7047                token() === SyntaxKind.AsteriskToken ||
7048                token() === SyntaxKind.OpenBracketToken) {
7049                const isAmbient = some(modifiers, isDeclareModifier);
7050                if (isAmbient) {
7051                    for (const m of modifiers!) {
7052                        (m as Mutable<Node>).flags |= NodeFlags.Ambient;
7053                    }
7054                    return doInsideOfContext(NodeFlags.Ambient, () => parsePropertyOrMethodDeclaration(pos, hasJSDoc, decorators, modifiers));
7055                }
7056                else {
7057                    return parsePropertyOrMethodDeclaration(pos, hasJSDoc, decorators, modifiers);
7058                }
7059            }
7060
7061            if (decorators || modifiers) {
7062                // treat this as a property declaration with a missing name.
7063                const name = createMissingNode<Identifier>(SyntaxKind.Identifier, /*reportAtCurrentPosition*/ true, Diagnostics.Declaration_expected);
7064                return parsePropertyDeclaration(pos, hasJSDoc, decorators, modifiers, name, /*questionToken*/ undefined);
7065            }
7066
7067            // 'isClassMemberStart' should have hinted not to attempt parsing.
7068            return Debug.fail("Should not have attempted to parse class member declaration.");
7069        }
7070
7071        function parseClassExpression(): ClassExpression {
7072            return <ClassExpression>parseClassDeclarationOrExpression(getNodePos(), hasPrecedingJSDocComment(), /*decorators*/ undefined, /*modifiers*/ undefined, SyntaxKind.ClassExpression);
7073        }
7074
7075        function parseClassDeclaration(pos: number, hasJSDoc: boolean, decorators: NodeArray<Decorator> | undefined, modifiers: NodeArray<Modifier> | undefined): ClassDeclaration {
7076            return <ClassDeclaration>parseClassDeclarationOrExpression(pos, hasJSDoc, decorators, modifiers, SyntaxKind.ClassDeclaration);
7077        }
7078
7079        function parseStructDeclaration(pos: number, hasJSDoc: boolean, decorators: NodeArray<Decorator> | undefined, modifiers: NodeArray<Modifier> | undefined): StructDeclaration {
7080            return parseStructDeclarationOrExpression(pos, hasJSDoc, decorators, modifiers);
7081        }
7082
7083        function parseClassDeclarationOrExpression(pos: number, hasJSDoc: boolean, decorators: NodeArray<Decorator> | undefined, modifiers: NodeArray<Modifier> | undefined, kind: ClassLikeDeclaration["kind"]): ClassLikeDeclaration {
7084            const savedAwaitContext = inAwaitContext();
7085            parseExpected(SyntaxKind.ClassKeyword);
7086            // We don't parse the name here in await context, instead we will report a grammar error in the checker.
7087            const name = parseNameOfClassDeclarationOrExpression();
7088            const typeParameters = parseTypeParameters();
7089            if (some(modifiers, isExportModifier)) setAwaitContext(/*value*/ true);
7090            const heritageClauses = parseHeritageClauses();
7091
7092            let members;
7093            if (parseExpected(SyntaxKind.OpenBraceToken)) {
7094                // ClassTail[Yield,Await] : (Modified) See 14.5
7095                //      ClassHeritage[?Yield,?Await]opt { ClassBody[?Yield,?Await]opt }
7096                members = parseClassMembers();
7097                parseExpected(SyntaxKind.CloseBraceToken);
7098            }
7099            else {
7100                members = createMissingList<ClassElement>();
7101            }
7102            setAwaitContext(savedAwaitContext);
7103            const node = kind === SyntaxKind.ClassDeclaration
7104                ? factory.createClassDeclaration(decorators, modifiers, name, typeParameters, heritageClauses, members)
7105                : factory.createClassExpression(decorators, modifiers, name, typeParameters, heritageClauses, members);
7106            return withJSDoc(finishNode(node, pos), hasJSDoc);
7107        }
7108
7109        function parseStructDeclarationOrExpression(pos: number, hasJSDoc: boolean, decorators: NodeArray<Decorator> | undefined, modifiers: NodeArray<Modifier> | undefined): StructDeclaration {
7110            const savedAwaitContext = inAwaitContext();
7111            parseExpected(SyntaxKind.StructKeyword);
7112            setStructContext(true);
7113            // We don't parse the name here in await context, instead we will report a grammar error in the checker.
7114            // struct Identifier logic is same to class Identifier
7115            const name = parseNameOfClassDeclarationOrExpression();
7116            currentStructName = name?.escapedText.toString();
7117            const typeParameters = parseTypeParameters();
7118            if (some(modifiers, isExportModifier)) setAwaitContext(/*value*/ true);
7119            let heritageClauses = parseHeritageClauses();
7120            const customComponent = sourceFileCompilerOptions.ets?.customComponent;
7121            if (!heritageClauses && customComponent) {
7122                heritageClauses = createVirtualHeritageClauses(customComponent);
7123            }
7124            let members;
7125            if (parseExpected(SyntaxKind.OpenBraceToken)) {
7126                // ClassTail[Yield,Await] : (Modified) See 14.5
7127                //      ClassHeritage[?Yield,?Await]opt { ClassBody[?Yield,?Await]opt }
7128                members = parseStructMembers(pos);
7129                parseExpected(SyntaxKind.CloseBraceToken);
7130            }
7131            else {
7132                members = createMissingList<ClassElement>();
7133            }
7134            setAwaitContext(savedAwaitContext);
7135            const node = factory.createStructDeclaration(decorators, modifiers, name, typeParameters, heritageClauses, members);
7136            currentStructName = undefined;
7137            structStylesComponents.clear();
7138            setStructContext(false);
7139            return withJSDoc(finishNode(node, pos), hasJSDoc);
7140        }
7141
7142        function createVirtualHeritageClauses(customComponent: string): NodeArray<HeritageClause> {
7143            const curPos = getNodePos();
7144            const clause = factory.createHeritageClause(
7145                SyntaxKind.ExtendsKeyword,
7146                createNodeArray([finishNode(factory.createExpressionWithTypeArguments(
7147                    finishNode(factory.createIdentifier(/*text*/ customComponent), curPos, /*end*/ undefined, /*virtual*/ true),
7148                /*typeArguments*/ undefined
7149                ), curPos)], curPos, /*end*/ undefined, /*hasTrailingComma*/ false)
7150            );
7151            return createNodeArray([finishNode(clause, curPos, /*end*/ undefined, /*virtual*/ true)], curPos, /*end*/ undefined, /*hasTrailingComma*/ false);
7152        }
7153
7154        function parseNameOfClassDeclarationOrExpression(): Identifier | undefined {
7155            // implements is a future reserved word so
7156            // 'class implements' might mean either
7157            // - class expression with omitted name, 'implements' starts heritage clause
7158            // - class with name 'implements'
7159            // 'isImplementsClause' helps to disambiguate between these two cases
7160            return isBindingIdentifier() && !isImplementsClause()
7161                ? createIdentifier(isBindingIdentifier())
7162                : undefined;
7163        }
7164
7165        function isImplementsClause() {
7166            return token() === SyntaxKind.ImplementsKeyword && lookAhead(nextTokenIsIdentifierOrKeyword);
7167        }
7168
7169        function parseHeritageClauses(): NodeArray<HeritageClause> | undefined {
7170            // ClassTail[Yield,Await] : (Modified) See 14.5
7171            //      ClassHeritage[?Yield,?Await]opt { ClassBody[?Yield,?Await]opt }
7172
7173            if (isHeritageClause()) {
7174                return parseList(ParsingContext.HeritageClauses, parseHeritageClause);
7175            }
7176
7177            return undefined;
7178        }
7179
7180        function parseHeritageClause(): HeritageClause {
7181            const pos = getNodePos();
7182            const tok = token();
7183            Debug.assert(tok === SyntaxKind.ExtendsKeyword || tok === SyntaxKind.ImplementsKeyword); // isListElement() should ensure this.
7184            nextToken();
7185            const types = parseDelimitedList(ParsingContext.HeritageClauseElement, parseExpressionWithTypeArguments);
7186            return finishNode(factory.createHeritageClause(tok, types), pos);
7187        }
7188
7189        function parseExpressionWithTypeArguments(): ExpressionWithTypeArguments {
7190            const pos = getNodePos();
7191            const expression = parseLeftHandSideExpressionOrHigher();
7192            const typeArguments = tryParseTypeArguments();
7193            return finishNode(factory.createExpressionWithTypeArguments(expression, typeArguments), pos);
7194        }
7195
7196        function tryParseTypeArguments(): NodeArray<TypeNode> | undefined {
7197            return token() === SyntaxKind.LessThanToken ?
7198                parseBracketedList(ParsingContext.TypeArguments, parseType, SyntaxKind.LessThanToken, SyntaxKind.GreaterThanToken) : undefined;
7199        }
7200
7201        function isHeritageClause(): boolean {
7202            return token() === SyntaxKind.ExtendsKeyword || token() === SyntaxKind.ImplementsKeyword;
7203        }
7204
7205        function parseClassMembers(): NodeArray<ClassElement> {
7206            return parseList(ParsingContext.ClassMembers, parseClassElement);
7207        }
7208
7209        function parseStructMembers(pos: number): NodeArray<ClassElement> {
7210            const structMembers = parseList(ParsingContext.ClassMembers, parseClassElement);
7211
7212            const virtualStructMembers: ClassElement[] = [];
7213            // create constructor function argument object properties
7214            const virtualParameterProperties: TypeElement[] = [];
7215            structMembers.forEach(member => {
7216                virtualStructMembers.push(member);
7217                if (member.kind === SyntaxKind.PropertyDeclaration) {
7218                    const property = <PropertyDeclaration>member;
7219                    virtualParameterProperties.push(
7220                        finishVirtualNode(
7221                            factory.createPropertySignature(property.modifiers, property.name, factory.createToken(SyntaxKind.QuestionToken), property.type)
7222                        )
7223                    );
7224                }
7225            });
7226            const parameters: ParameterDeclaration[] = [];
7227            if (virtualParameterProperties.length) {
7228                const type = finishVirtualNode(factory.createTypeLiteralNode(createNodeArray(virtualParameterProperties, 0, 0)));
7229                parameters.push(
7230                    finishVirtualNode(
7231                        factory.createParameterDeclaration(/*decorators*/ undefined, /*modifiers*/ undefined, /*dotDotDotToken*/ undefined,
7232                            finishVirtualNode(factory.createIdentifier("value")), factory.createToken(SyntaxKind.QuestionToken), type
7233                        )
7234                    )
7235                );
7236            }
7237            const emptyBody = finishVirtualNode(factory.createBlock(createNodeArray([], 0, 0)));
7238            const virtualConstructor = factory.createConstructorDeclaration(/*decorators*/ undefined, /*modifier*/ undefined, createNodeArray(parameters, 0, 0), emptyBody);
7239
7240            virtualStructMembers.unshift(finishVirtualNode(virtualConstructor, pos, pos));
7241
7242            return createNodeArray(virtualStructMembers, structMembers.pos);
7243        }
7244
7245        function finishVirtualNode<T extends Node>(node: T, start = 0, end = 0) {
7246            return finishNode(node, start, end, /*virtual*/ true);
7247        }
7248
7249        function parseInterfaceDeclaration(pos: number, hasJSDoc: boolean, decorators: NodeArray<Decorator> | undefined, modifiers: NodeArray<Modifier> | undefined): InterfaceDeclaration {
7250            parseExpected(SyntaxKind.InterfaceKeyword);
7251            const name = parseIdentifier();
7252            const typeParameters = parseTypeParameters();
7253            const heritageClauses = parseHeritageClauses();
7254            const members = parseObjectTypeMembers();
7255            const node = factory.createInterfaceDeclaration(decorators, modifiers, name, typeParameters, heritageClauses, members);
7256            return withJSDoc(finishNode(node, pos), hasJSDoc);
7257        }
7258
7259        function parseTypeAliasDeclaration(pos: number, hasJSDoc: boolean, decorators: NodeArray<Decorator> | undefined, modifiers: NodeArray<Modifier> | undefined): TypeAliasDeclaration {
7260            parseExpected(SyntaxKind.TypeKeyword);
7261            const name = parseIdentifier();
7262            const typeParameters = parseTypeParameters();
7263            parseExpected(SyntaxKind.EqualsToken);
7264            const type = token() === SyntaxKind.IntrinsicKeyword && tryParse(parseKeywordAndNoDot) || parseType();
7265            parseSemicolon();
7266            const node = factory.createTypeAliasDeclaration(decorators, modifiers, name, typeParameters, type);
7267            return withJSDoc(finishNode(node, pos), hasJSDoc);
7268        }
7269
7270        // In an ambient declaration, the grammar only allows integer literals as initializers.
7271        // In a non-ambient declaration, the grammar allows uninitialized members only in a
7272        // ConstantEnumMemberSection, which starts at the beginning of an enum declaration
7273        // or any time an integer literal initializer is encountered.
7274        function parseEnumMember(): EnumMember {
7275            const pos = getNodePos();
7276            const hasJSDoc = hasPrecedingJSDocComment();
7277            const name = parsePropertyName();
7278            const initializer = allowInAnd(parseInitializer);
7279            return withJSDoc(finishNode(factory.createEnumMember(name, initializer), pos), hasJSDoc);
7280        }
7281
7282        function parseEnumDeclaration(pos: number, hasJSDoc: boolean, decorators: NodeArray<Decorator> | undefined, modifiers: NodeArray<Modifier> | undefined): EnumDeclaration {
7283            parseExpected(SyntaxKind.EnumKeyword);
7284            const name = parseIdentifier();
7285            let members;
7286            if (parseExpected(SyntaxKind.OpenBraceToken)) {
7287                members = doOutsideOfYieldAndAwaitContext(() => parseDelimitedList(ParsingContext.EnumMembers, parseEnumMember));
7288                parseExpected(SyntaxKind.CloseBraceToken);
7289            }
7290            else {
7291                members = createMissingList<EnumMember>();
7292            }
7293            const node = factory.createEnumDeclaration(decorators, modifiers, name, members);
7294            return withJSDoc(finishNode(node, pos), hasJSDoc);
7295        }
7296
7297        function parseModuleBlock(): ModuleBlock {
7298            const pos = getNodePos();
7299            let statements;
7300            if (parseExpected(SyntaxKind.OpenBraceToken)) {
7301                statements = parseList(ParsingContext.BlockStatements, parseStatement);
7302                parseExpected(SyntaxKind.CloseBraceToken);
7303            }
7304            else {
7305                statements = createMissingList<Statement>();
7306            }
7307            return finishNode(factory.createModuleBlock(statements), pos);
7308        }
7309
7310        function parseModuleOrNamespaceDeclaration(pos: number, hasJSDoc: boolean, decorators: NodeArray<Decorator> | undefined, modifiers: NodeArray<Modifier> | undefined, flags: NodeFlags): ModuleDeclaration {
7311            // If we are parsing a dotted namespace name, we want to
7312            // propagate the 'Namespace' flag across the names if set.
7313            const namespaceFlag = flags & NodeFlags.Namespace;
7314            const name = parseIdentifier();
7315            const body = parseOptional(SyntaxKind.DotToken)
7316                ? <NamespaceDeclaration>parseModuleOrNamespaceDeclaration(getNodePos(), /*hasJSDoc*/ false, /*decorators*/ undefined, /*modifiers*/ undefined, NodeFlags.NestedNamespace | namespaceFlag)
7317                : parseModuleBlock();
7318            const node = factory.createModuleDeclaration(decorators, modifiers, name, body, flags);
7319            return withJSDoc(finishNode(node, pos), hasJSDoc);
7320        }
7321
7322        function parseAmbientExternalModuleDeclaration(pos: number, hasJSDoc: boolean, decorators: NodeArray<Decorator> | undefined, modifiers: NodeArray<Modifier> | undefined): ModuleDeclaration {
7323            let flags: NodeFlags = 0;
7324            let name;
7325            if (token() === SyntaxKind.GlobalKeyword) {
7326                // parse 'global' as name of global scope augmentation
7327                name = parseIdentifier();
7328                flags |= NodeFlags.GlobalAugmentation;
7329            }
7330            else {
7331                name = <StringLiteral>parseLiteralNode();
7332                name.text = internIdentifier(name.text);
7333            }
7334            let body: ModuleBlock | undefined;
7335            if (token() === SyntaxKind.OpenBraceToken) {
7336                body = parseModuleBlock();
7337            }
7338            else {
7339                parseSemicolon();
7340            }
7341            const node = factory.createModuleDeclaration(decorators, modifiers, name, body, flags);
7342            return withJSDoc(finishNode(node, pos), hasJSDoc);
7343        }
7344
7345        function parseModuleDeclaration(pos: number, hasJSDoc: boolean, decorators: NodeArray<Decorator> | undefined, modifiers: NodeArray<Modifier> | undefined): ModuleDeclaration {
7346            let flags: NodeFlags = 0;
7347            if (token() === SyntaxKind.GlobalKeyword) {
7348                // global augmentation
7349                return parseAmbientExternalModuleDeclaration(pos, hasJSDoc, decorators, modifiers);
7350            }
7351            else if (parseOptional(SyntaxKind.NamespaceKeyword)) {
7352                flags |= NodeFlags.Namespace;
7353            }
7354            else {
7355                parseExpected(SyntaxKind.ModuleKeyword);
7356                if (token() === SyntaxKind.StringLiteral) {
7357                    return parseAmbientExternalModuleDeclaration(pos, hasJSDoc, decorators, modifiers);
7358                }
7359            }
7360            return parseModuleOrNamespaceDeclaration(pos, hasJSDoc, decorators, modifiers, flags);
7361        }
7362
7363        function isExternalModuleReference() {
7364            return token() === SyntaxKind.RequireKeyword &&
7365                lookAhead(nextTokenIsOpenParen);
7366        }
7367
7368        function nextTokenIsOpenParen() {
7369            return nextToken() === SyntaxKind.OpenParenToken;
7370        }
7371
7372        function nextTokenIsSlash() {
7373            return nextToken() === SyntaxKind.SlashToken;
7374        }
7375
7376        function parseNamespaceExportDeclaration(pos: number, hasJSDoc: boolean, decorators: NodeArray<Decorator> | undefined, modifiers: NodeArray<Modifier> | undefined): NamespaceExportDeclaration {
7377            parseExpected(SyntaxKind.AsKeyword);
7378            parseExpected(SyntaxKind.NamespaceKeyword);
7379            const name = parseIdentifier();
7380            parseSemicolon();
7381            const node = factory.createNamespaceExportDeclaration(name);
7382            // NamespaceExportDeclaration nodes cannot have decorators or modifiers, so we attach them here so we can report them in the grammar checker
7383            node.decorators = decorators;
7384            node.modifiers = modifiers;
7385            return withJSDoc(finishNode(node, pos), hasJSDoc);
7386        }
7387
7388        function parseImportDeclarationOrImportEqualsDeclaration(pos: number, hasJSDoc: boolean, decorators: NodeArray<Decorator> | undefined, modifiers: NodeArray<Modifier> | undefined): ImportEqualsDeclaration | ImportDeclaration {
7389            parseExpected(SyntaxKind.ImportKeyword);
7390
7391            const afterImportPos = scanner.getStartPos();
7392
7393            // We don't parse the identifier here in await context, instead we will report a grammar error in the checker.
7394            let identifier: Identifier | undefined;
7395            if (isIdentifier()) {
7396                identifier = parseIdentifier();
7397            }
7398
7399            let isTypeOnly = false;
7400            if (token() !== SyntaxKind.FromKeyword &&
7401                identifier?.escapedText === "type" &&
7402                (isIdentifier() || tokenAfterImportDefinitelyProducesImportDeclaration())
7403            ) {
7404                isTypeOnly = true;
7405                identifier = isIdentifier() ? parseIdentifier() : undefined;
7406            }
7407
7408            if (identifier && !tokenAfterImportedIdentifierDefinitelyProducesImportDeclaration()) {
7409                return parseImportEqualsDeclaration(pos, hasJSDoc, decorators, modifiers, identifier, isTypeOnly);
7410            }
7411
7412            // ImportDeclaration:
7413            //  import ImportClause from ModuleSpecifier ;
7414            //  import ModuleSpecifier;
7415            let importClause: ImportClause | undefined;
7416            if (identifier || // import id
7417                token() === SyntaxKind.AsteriskToken || // import *
7418                token() === SyntaxKind.OpenBraceToken    // import {
7419            ) {
7420                importClause = parseImportClause(identifier, afterImportPos, isTypeOnly);
7421                parseExpected(SyntaxKind.FromKeyword);
7422            }
7423
7424            const moduleSpecifier = parseModuleSpecifier();
7425            parseSemicolon();
7426            const node = factory.createImportDeclaration(decorators, modifiers, importClause, moduleSpecifier);
7427            return withJSDoc(finishNode(node, pos), hasJSDoc);
7428        }
7429
7430        function tokenAfterImportDefinitelyProducesImportDeclaration() {
7431            return token() === SyntaxKind.AsteriskToken || token() === SyntaxKind.OpenBraceToken;
7432        }
7433
7434        function tokenAfterImportedIdentifierDefinitelyProducesImportDeclaration() {
7435            // In `import id ___`, the current token decides whether to produce
7436            // an ImportDeclaration or ImportEqualsDeclaration.
7437            return token() === SyntaxKind.CommaToken || token() === SyntaxKind.FromKeyword;
7438        }
7439
7440        function parseImportEqualsDeclaration(pos: number, hasJSDoc: boolean, decorators: NodeArray<Decorator> | undefined, modifiers: NodeArray<Modifier> | undefined, identifier: Identifier, isTypeOnly: boolean): ImportEqualsDeclaration {
7441            parseExpected(SyntaxKind.EqualsToken);
7442            const moduleReference = parseModuleReference();
7443            parseSemicolon();
7444            const node = factory.createImportEqualsDeclaration(decorators, modifiers, isTypeOnly, identifier, moduleReference);
7445            const finished = withJSDoc(finishNode(node, pos), hasJSDoc);
7446            return finished;
7447        }
7448
7449        function parseImportClause(identifier: Identifier | undefined, pos: number, isTypeOnly: boolean) {
7450            // ImportClause:
7451            //  ImportedDefaultBinding
7452            //  NameSpaceImport
7453            //  NamedImports
7454            //  ImportedDefaultBinding, NameSpaceImport
7455            //  ImportedDefaultBinding, NamedImports
7456
7457            // If there was no default import or if there is comma token after default import
7458            // parse namespace or named imports
7459            let namedBindings: NamespaceImport | NamedImports | undefined;
7460            if (!identifier ||
7461                parseOptional(SyntaxKind.CommaToken)) {
7462                namedBindings = token() === SyntaxKind.AsteriskToken ? parseNamespaceImport() : parseNamedImportsOrExports(SyntaxKind.NamedImports);
7463            }
7464
7465            return finishNode(factory.createImportClause(isTypeOnly, identifier, namedBindings), pos);
7466        }
7467
7468        function parseModuleReference() {
7469            return isExternalModuleReference()
7470                ? parseExternalModuleReference()
7471                : parseEntityName(/*allowReservedWords*/ false);
7472        }
7473
7474        function parseExternalModuleReference() {
7475            const pos = getNodePos();
7476            parseExpected(SyntaxKind.RequireKeyword);
7477            parseExpected(SyntaxKind.OpenParenToken);
7478            const expression = parseModuleSpecifier();
7479            parseExpected(SyntaxKind.CloseParenToken);
7480            return finishNode(factory.createExternalModuleReference(expression), pos);
7481        }
7482
7483        function parseModuleSpecifier(): Expression {
7484            if (token() === SyntaxKind.StringLiteral) {
7485                const result = parseLiteralNode();
7486                result.text = internIdentifier(result.text);
7487                return result;
7488            }
7489            else {
7490                // We allow arbitrary expressions here, even though the grammar only allows string
7491                // literals.  We check to ensure that it is only a string literal later in the grammar
7492                // check pass.
7493                return parseExpression();
7494            }
7495        }
7496
7497        function parseNamespaceImport(): NamespaceImport {
7498            // NameSpaceImport:
7499            //  * as ImportedBinding
7500            const pos = getNodePos();
7501            parseExpected(SyntaxKind.AsteriskToken);
7502            parseExpected(SyntaxKind.AsKeyword);
7503            const name = parseIdentifier();
7504            return finishNode(factory.createNamespaceImport(name), pos);
7505        }
7506
7507        function parseNamedImportsOrExports(kind: SyntaxKind.NamedImports): NamedImports;
7508        function parseNamedImportsOrExports(kind: SyntaxKind.NamedExports): NamedExports;
7509        function parseNamedImportsOrExports(kind: SyntaxKind): NamedImportsOrExports {
7510            const pos = getNodePos();
7511
7512            // NamedImports:
7513            //  { }
7514            //  { ImportsList }
7515            //  { ImportsList, }
7516
7517            // ImportsList:
7518            //  ImportSpecifier
7519            //  ImportsList, ImportSpecifier
7520            const node = kind === SyntaxKind.NamedImports
7521                ? factory.createNamedImports(parseBracketedList(ParsingContext.ImportOrExportSpecifiers, parseImportSpecifier, SyntaxKind.OpenBraceToken, SyntaxKind.CloseBraceToken))
7522                : factory.createNamedExports(parseBracketedList(ParsingContext.ImportOrExportSpecifiers, parseExportSpecifier, SyntaxKind.OpenBraceToken, SyntaxKind.CloseBraceToken));
7523            return finishNode(node, pos);
7524        }
7525
7526        function parseExportSpecifier() {
7527            return parseImportOrExportSpecifier(SyntaxKind.ExportSpecifier) as ExportSpecifier;
7528        }
7529
7530        function parseImportSpecifier() {
7531            return parseImportOrExportSpecifier(SyntaxKind.ImportSpecifier) as ImportSpecifier;
7532        }
7533
7534        function parseImportOrExportSpecifier(kind: SyntaxKind): ImportOrExportSpecifier {
7535            const pos = getNodePos();
7536            // ImportSpecifier:
7537            //   BindingIdentifier
7538            //   IdentifierName as BindingIdentifier
7539            // ExportSpecifier:
7540            //   IdentifierName
7541            //   IdentifierName as IdentifierName
7542            let checkIdentifierIsKeyword = isKeyword(token()) && !isIdentifier();
7543            let checkIdentifierStart = scanner.getTokenPos();
7544            let checkIdentifierEnd = scanner.getTextPos();
7545            const identifierName = parseIdentifierName();
7546            let propertyName: Identifier | undefined;
7547            let name: Identifier;
7548            if (token() === SyntaxKind.AsKeyword) {
7549                propertyName = identifierName;
7550                parseExpected(SyntaxKind.AsKeyword);
7551                checkIdentifierIsKeyword = isKeyword(token()) && !isIdentifier();
7552                checkIdentifierStart = scanner.getTokenPos();
7553                checkIdentifierEnd = scanner.getTextPos();
7554                name = parseIdentifierName();
7555            }
7556            else {
7557                name = identifierName;
7558            }
7559            if (kind === SyntaxKind.ImportSpecifier && checkIdentifierIsKeyword) {
7560                parseErrorAt(checkIdentifierStart, checkIdentifierEnd, Diagnostics.Identifier_expected);
7561            }
7562            const node = kind === SyntaxKind.ImportSpecifier
7563                ? factory.createImportSpecifier(propertyName, name)
7564                : factory.createExportSpecifier(propertyName, name);
7565            return finishNode(node, pos);
7566        }
7567
7568        function parseNamespaceExport(pos: number): NamespaceExport {
7569            return finishNode(factory.createNamespaceExport(parseIdentifierName()), pos);
7570        }
7571
7572        function parseExportDeclaration(pos: number, hasJSDoc: boolean, decorators: NodeArray<Decorator> | undefined, modifiers: NodeArray<Modifier> | undefined): ExportDeclaration {
7573            const savedAwaitContext = inAwaitContext();
7574            setAwaitContext(/*value*/ true);
7575            let exportClause: NamedExportBindings | undefined;
7576            let moduleSpecifier: Expression | undefined;
7577            const isTypeOnly = parseOptional(SyntaxKind.TypeKeyword);
7578            const namespaceExportPos = getNodePos();
7579            if (parseOptional(SyntaxKind.AsteriskToken)) {
7580                if (parseOptional(SyntaxKind.AsKeyword)) {
7581                    exportClause = parseNamespaceExport(namespaceExportPos);
7582                }
7583                parseExpected(SyntaxKind.FromKeyword);
7584                moduleSpecifier = parseModuleSpecifier();
7585            }
7586            else {
7587                exportClause = parseNamedImportsOrExports(SyntaxKind.NamedExports);
7588                // It is not uncommon to accidentally omit the 'from' keyword. Additionally, in editing scenarios,
7589                // the 'from' keyword can be parsed as a named export when the export clause is unterminated (i.e. `export { from "moduleName";`)
7590                // If we don't have a 'from' keyword, see if we have a string literal such that ASI won't take effect.
7591                if (token() === SyntaxKind.FromKeyword || (token() === SyntaxKind.StringLiteral && !scanner.hasPrecedingLineBreak())) {
7592                    parseExpected(SyntaxKind.FromKeyword);
7593                    moduleSpecifier = parseModuleSpecifier();
7594                }
7595            }
7596            parseSemicolon();
7597            setAwaitContext(savedAwaitContext);
7598            const node = factory.createExportDeclaration(decorators, modifiers, isTypeOnly, exportClause, moduleSpecifier);
7599            return withJSDoc(finishNode(node, pos), hasJSDoc);
7600        }
7601
7602        function parseExportAssignment(pos: number, hasJSDoc: boolean, decorators: NodeArray<Decorator> | undefined, modifiers: NodeArray<Modifier> | undefined): ExportAssignment {
7603            const savedAwaitContext = inAwaitContext();
7604            setAwaitContext(/*value*/ true);
7605            let isExportEquals: boolean | undefined;
7606            if (parseOptional(SyntaxKind.EqualsToken)) {
7607                isExportEquals = true;
7608            }
7609            else {
7610                parseExpected(SyntaxKind.DefaultKeyword);
7611            }
7612            const expression = parseAssignmentExpressionOrHigher();
7613            parseSemicolon();
7614            setAwaitContext(savedAwaitContext);
7615            const node = factory.createExportAssignment(decorators, modifiers, isExportEquals, expression);
7616            return withJSDoc(finishNode(node, pos), hasJSDoc);
7617        }
7618
7619        function setExternalModuleIndicator(sourceFile: SourceFile) {
7620            // Try to use the first top-level import/export when available, then
7621            // fall back to looking for an 'import.meta' somewhere in the tree if necessary.
7622            sourceFile.externalModuleIndicator =
7623                    forEach(sourceFile.statements, isAnExternalModuleIndicatorNode) ||
7624                    getImportMetaIfNecessary(sourceFile);
7625        }
7626
7627        function isAnExternalModuleIndicatorNode(node: Node) {
7628            return hasModifierOfKind(node, SyntaxKind.ExportKeyword)
7629                || isImportEqualsDeclaration(node) && ts.isExternalModuleReference(node.moduleReference)
7630                || isImportDeclaration(node)
7631                || isExportAssignment(node)
7632                || isExportDeclaration(node) ? node : undefined;
7633        }
7634
7635        function getImportMetaIfNecessary(sourceFile: SourceFile) {
7636            return sourceFile.flags & NodeFlags.PossiblyContainsImportMeta ?
7637                walkTreeForExternalModuleIndicators(sourceFile) :
7638                undefined;
7639        }
7640
7641        function walkTreeForExternalModuleIndicators(node: Node): Node | undefined {
7642            return isImportMeta(node) ? node : forEachChild(node, walkTreeForExternalModuleIndicators);
7643        }
7644
7645        /** Do not use hasModifier inside the parser; it relies on parent pointers. Use this instead. */
7646        function hasModifierOfKind(node: Node, kind: SyntaxKind) {
7647            return some(node.modifiers, m => m.kind === kind);
7648        }
7649
7650        function isImportMeta(node: Node): boolean {
7651            return isMetaProperty(node) && node.keywordToken === SyntaxKind.ImportKeyword && node.name.escapedText === "meta";
7652        }
7653
7654        const enum ParsingContext {
7655            SourceElements,            // Elements in source file
7656            BlockStatements,           // Statements in block
7657            SwitchClauses,             // Clauses in switch statement
7658            SwitchClauseStatements,    // Statements in switch clause
7659            TypeMembers,               // Members in interface or type literal
7660            ClassMembers,              // Members in class declaration
7661            EnumMembers,               // Members in enum declaration
7662            HeritageClauseElement,     // Elements in a heritage clause
7663            VariableDeclarations,      // Variable declarations in variable statement
7664            ObjectBindingElements,     // Binding elements in object binding list
7665            ArrayBindingElements,      // Binding elements in array binding list
7666            ArgumentExpressions,       // Expressions in argument list
7667            ObjectLiteralMembers,      // Members in object literal
7668            JsxAttributes,             // Attributes in jsx element
7669            JsxChildren,               // Things between opening and closing JSX tags
7670            ArrayLiteralMembers,       // Members in array literal
7671            Parameters,                // Parameters in parameter list
7672            JSDocParameters,           // JSDoc parameters in parameter list of JSDoc function type
7673            RestProperties,            // Property names in a rest type list
7674            TypeParameters,            // Type parameters in type parameter list
7675            TypeArguments,             // Type arguments in type argument list
7676            TupleElementTypes,         // Element types in tuple element type list
7677            HeritageClauses,           // Heritage clauses for a class or interface declaration.
7678            ImportOrExportSpecifiers,  // Named import clause's import specifier list
7679            Count                      // Number of parsing contexts
7680        }
7681
7682        const enum Tristate {
7683            False,
7684            True,
7685            Unknown
7686        }
7687
7688        export namespace JSDocParser {
7689            export function parseJSDocTypeExpressionForTests(content: string, start: number | undefined, length: number | undefined): { jsDocTypeExpression: JSDocTypeExpression, diagnostics: Diagnostic[] } | undefined {
7690                initializeState("file.js", content, ScriptTarget.Latest, /*_syntaxCursor:*/ undefined, ScriptKind.JS);
7691                scanner.setText(content, start, length);
7692                currentToken = scanner.scan();
7693                const jsDocTypeExpression = parseJSDocTypeExpression();
7694
7695                const sourceFile = createSourceFile("file.js", ScriptTarget.Latest, ScriptKind.JS, /*isDeclarationFile*/ false, [], factory.createToken(SyntaxKind.EndOfFileToken), NodeFlags.None);
7696                const diagnostics = attachFileToDiagnostics(parseDiagnostics, sourceFile);
7697                if (jsDocDiagnostics) {
7698                    sourceFile.jsDocDiagnostics = attachFileToDiagnostics(jsDocDiagnostics, sourceFile);
7699                }
7700
7701                clearState();
7702
7703                return jsDocTypeExpression ? { jsDocTypeExpression, diagnostics } : undefined;
7704            }
7705
7706            // Parses out a JSDoc type expression.
7707            export function parseJSDocTypeExpression(mayOmitBraces?: boolean): JSDocTypeExpression {
7708                const pos = getNodePos();
7709                const hasBrace = (mayOmitBraces ? parseOptional : parseExpected)(SyntaxKind.OpenBraceToken);
7710                const type = doInsideOfContext(NodeFlags.JSDoc, parseJSDocType);
7711                if (!mayOmitBraces || hasBrace) {
7712                    parseExpectedJSDoc(SyntaxKind.CloseBraceToken);
7713                }
7714
7715                const result = factory.createJSDocTypeExpression(type);
7716                fixupParentReferences(result);
7717                return finishNode(result, pos);
7718            }
7719
7720            export function parseJSDocNameReference(): JSDocNameReference {
7721                const pos = getNodePos();
7722                const hasBrace = parseOptional(SyntaxKind.OpenBraceToken);
7723                const entityName = parseEntityName(/* allowReservedWords*/ false);
7724                if (hasBrace) {
7725                    parseExpectedJSDoc(SyntaxKind.CloseBraceToken);
7726                }
7727
7728                const result = factory.createJSDocNameReference(entityName);
7729                fixupParentReferences(result);
7730                return finishNode(result, pos);
7731            }
7732
7733            export function parseIsolatedJSDocComment(content: string, start: number | undefined, length: number | undefined): { jsDoc: JSDoc, diagnostics: Diagnostic[] } | undefined {
7734                initializeState("", content, ScriptTarget.Latest, /*_syntaxCursor:*/ undefined, ScriptKind.JS);
7735                const jsDoc = doInsideOfContext(NodeFlags.JSDoc, () => parseJSDocCommentWorker(start, length));
7736
7737                const sourceFile = <SourceFile>{ languageVariant: LanguageVariant.Standard, text: content };
7738                const diagnostics = attachFileToDiagnostics(parseDiagnostics, sourceFile);
7739                clearState();
7740
7741                return jsDoc ? { jsDoc, diagnostics } : undefined;
7742            }
7743
7744            export function parseJSDocComment(parent: HasJSDoc, start: number, length: number): JSDoc | undefined {
7745                const saveToken = currentToken;
7746                const saveParseDiagnosticsLength = parseDiagnostics.length;
7747                const saveParseErrorBeforeNextFinishedNode = parseErrorBeforeNextFinishedNode;
7748
7749                const comment = doInsideOfContext(NodeFlags.JSDoc, () => parseJSDocCommentWorker(start, length));
7750                setParent(comment, parent);
7751
7752                if (contextFlags & NodeFlags.JavaScriptFile) {
7753                    if (!jsDocDiagnostics) {
7754                        jsDocDiagnostics = [];
7755                    }
7756                    jsDocDiagnostics.push(...parseDiagnostics);
7757                }
7758                currentToken = saveToken;
7759                parseDiagnostics.length = saveParseDiagnosticsLength;
7760                parseErrorBeforeNextFinishedNode = saveParseErrorBeforeNextFinishedNode;
7761                return comment;
7762            }
7763
7764            const enum JSDocState {
7765                BeginningOfLine,
7766                SawAsterisk,
7767                SavingComments,
7768                SavingBackticks, // NOTE: Only used when parsing tag comments
7769            }
7770
7771            const enum PropertyLikeParse {
7772                Property = 1 << 0,
7773                Parameter = 1 << 1,
7774                CallbackParameter = 1 << 2,
7775            }
7776
7777            function parseJSDocCommentWorker(start = 0, length: number | undefined): JSDoc | undefined {
7778                const content = sourceText;
7779                const end = length === undefined ? content.length : start + length;
7780                length = end - start;
7781
7782                Debug.assert(start >= 0);
7783                Debug.assert(start <= end);
7784                Debug.assert(end <= content.length);
7785
7786                // Check for /** (JSDoc opening part)
7787                if (!isJSDocLikeText(content, start)) {
7788                    return undefined;
7789                }
7790
7791                let tags: JSDocTag[];
7792                let tagsPos: number;
7793                let tagsEnd: number;
7794                const comments: string[] = [];
7795
7796                // + 3 for leading /**, - 5 in total for /** */
7797                return scanner.scanRange(start + 3, length - 5, () => {
7798                    // Initially we can parse out a tag.  We also have seen a starting asterisk.
7799                    // This is so that /** * @type */ doesn't parse.
7800                    let state = JSDocState.SawAsterisk;
7801                    let margin: number | undefined;
7802                    // + 4 for leading '/** '
7803                    // + 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
7804                    let indent = start - (content.lastIndexOf("\n", start) + 1) + 4;
7805                    function pushComment(text: string) {
7806                        if (!margin) {
7807                            margin = indent;
7808                        }
7809                        comments.push(text);
7810                        indent += text.length;
7811                    }
7812
7813                    nextTokenJSDoc();
7814                    while (parseOptionalJsdoc(SyntaxKind.WhitespaceTrivia));
7815                    if (parseOptionalJsdoc(SyntaxKind.NewLineTrivia)) {
7816                        state = JSDocState.BeginningOfLine;
7817                        indent = 0;
7818                    }
7819                    loop: while (true) {
7820                        switch (token()) {
7821                            case SyntaxKind.AtToken:
7822                                if (state === JSDocState.BeginningOfLine || state === JSDocState.SawAsterisk) {
7823                                    removeTrailingWhitespace(comments);
7824                                    addTag(parseTag(indent));
7825                                    // NOTE: According to usejsdoc.org, a tag goes to end of line, except the last tag.
7826                                    // Real-world comments may break this rule, so "BeginningOfLine" will not be a real line beginning
7827                                    // for malformed examples like `/** @param {string} x @returns {number} the length */`
7828                                    state = JSDocState.BeginningOfLine;
7829                                    margin = undefined;
7830                                }
7831                                else {
7832                                    pushComment(scanner.getTokenText());
7833                                }
7834                                break;
7835                            case SyntaxKind.NewLineTrivia:
7836                                comments.push(scanner.getTokenText());
7837                                state = JSDocState.BeginningOfLine;
7838                                indent = 0;
7839                                break;
7840                            case SyntaxKind.AsteriskToken:
7841                                const asterisk = scanner.getTokenText();
7842                                if (state === JSDocState.SawAsterisk || state === JSDocState.SavingComments) {
7843                                    // If we've already seen an asterisk, then we can no longer parse a tag on this line
7844                                    state = JSDocState.SavingComments;
7845                                    pushComment(asterisk);
7846                                }
7847                                else {
7848                                    // Ignore the first asterisk on a line
7849                                    state = JSDocState.SawAsterisk;
7850                                    indent += asterisk.length;
7851                                }
7852                                break;
7853                            case SyntaxKind.WhitespaceTrivia:
7854                                // only collect whitespace if we're already saving comments or have just crossed the comment indent margin
7855                                const whitespace = scanner.getTokenText();
7856                                if (state === JSDocState.SavingComments) {
7857                                    comments.push(whitespace);
7858                                }
7859                                else if (margin !== undefined && indent + whitespace.length > margin) {
7860                                    comments.push(whitespace.slice(margin - indent));
7861                                }
7862                                indent += whitespace.length;
7863                                break;
7864                            case SyntaxKind.EndOfFileToken:
7865                                break loop;
7866                            default:
7867                                // Anything else is doc comment text. We just save it. Because it
7868                                // wasn't a tag, we can no longer parse a tag on this line until we hit the next
7869                                // line break.
7870                                state = JSDocState.SavingComments;
7871                                pushComment(scanner.getTokenText());
7872                                break;
7873                        }
7874                        nextTokenJSDoc();
7875                    }
7876                    removeLeadingNewlines(comments);
7877                    removeTrailingWhitespace(comments);
7878                    return createJSDocComment();
7879                });
7880
7881                function removeLeadingNewlines(comments: string[]) {
7882                    while (comments.length && (comments[0] === "\n" || comments[0] === "\r")) {
7883                        comments.shift();
7884                    }
7885                }
7886
7887                function removeTrailingWhitespace(comments: string[]) {
7888                    while (comments.length && comments[comments.length - 1].trim() === "") {
7889                        comments.pop();
7890                    }
7891                }
7892
7893                function createJSDocComment(): JSDoc {
7894                    const comment = comments.length ? comments.join("") : undefined;
7895                    const tagsArray = tags && createNodeArray(tags, tagsPos, tagsEnd);
7896                    return finishNode(factory.createJSDocComment(comment, tagsArray), start, end);
7897                }
7898
7899                function isNextNonwhitespaceTokenEndOfFile(): boolean {
7900                    // We must use infinite lookahead, as there could be any number of newlines :(
7901                    while (true) {
7902                        nextTokenJSDoc();
7903                        if (token() === SyntaxKind.EndOfFileToken) {
7904                            return true;
7905                        }
7906                        if (!(token() === SyntaxKind.WhitespaceTrivia || token() === SyntaxKind.NewLineTrivia)) {
7907                            return false;
7908                        }
7909                    }
7910                }
7911
7912                function skipWhitespace(): void {
7913                    if (token() === SyntaxKind.WhitespaceTrivia || token() === SyntaxKind.NewLineTrivia) {
7914                        if (lookAhead(isNextNonwhitespaceTokenEndOfFile)) {
7915                            return; // Don't skip whitespace prior to EoF (or end of comment) - that shouldn't be included in any node's range
7916                        }
7917                    }
7918                    while (token() === SyntaxKind.WhitespaceTrivia || token() === SyntaxKind.NewLineTrivia) {
7919                        nextTokenJSDoc();
7920                    }
7921                }
7922
7923                function skipWhitespaceOrAsterisk(): string {
7924                    if (token() === SyntaxKind.WhitespaceTrivia || token() === SyntaxKind.NewLineTrivia) {
7925                        if (lookAhead(isNextNonwhitespaceTokenEndOfFile)) {
7926                            return ""; // Don't skip whitespace prior to EoF (or end of comment) - that shouldn't be included in any node's range
7927                        }
7928                    }
7929
7930                    let precedingLineBreak = scanner.hasPrecedingLineBreak();
7931                    let seenLineBreak = false;
7932                    let indentText = "";
7933                    while ((precedingLineBreak && token() === SyntaxKind.AsteriskToken) || token() === SyntaxKind.WhitespaceTrivia || token() === SyntaxKind.NewLineTrivia) {
7934                        indentText += scanner.getTokenText();
7935                        if (token() === SyntaxKind.NewLineTrivia) {
7936                            precedingLineBreak = true;
7937                            seenLineBreak = true;
7938                            indentText = "";
7939                        }
7940                        else if (token() === SyntaxKind.AsteriskToken) {
7941                            precedingLineBreak = false;
7942                        }
7943                        nextTokenJSDoc();
7944                    }
7945                    return seenLineBreak ? indentText : "";
7946                }
7947
7948                function parseTag(margin: number) {
7949                    Debug.assert(token() === SyntaxKind.AtToken);
7950                    const start = scanner.getTokenPos();
7951                    nextTokenJSDoc();
7952
7953                    const tagName = parseJSDocIdentifierName(/*message*/ undefined);
7954                    const indentText = skipWhitespaceOrAsterisk();
7955
7956                    let tag: JSDocTag | undefined;
7957                    switch (tagName.escapedText) {
7958                        case "author":
7959                            tag = parseAuthorTag(start, tagName, margin, indentText);
7960                            break;
7961                        case "implements":
7962                            tag = parseImplementsTag(start, tagName, margin, indentText);
7963                            break;
7964                        case "augments":
7965                        case "extends":
7966                            tag = parseAugmentsTag(start, tagName, margin, indentText);
7967                            break;
7968                        case "class":
7969                        case "constructor":
7970                            tag = parseSimpleTag(start, factory.createJSDocClassTag, tagName, margin, indentText);
7971                            break;
7972                        case "public":
7973                            tag = parseSimpleTag(start, factory.createJSDocPublicTag, tagName, margin, indentText);
7974                            break;
7975                        case "private":
7976                            tag = parseSimpleTag(start, factory.createJSDocPrivateTag, tagName, margin, indentText);
7977                            break;
7978                        case "protected":
7979                            tag = parseSimpleTag(start, factory.createJSDocProtectedTag, tagName, margin, indentText);
7980                            break;
7981                        case "readonly":
7982                            tag = parseSimpleTag(start, factory.createJSDocReadonlyTag, tagName, margin, indentText);
7983                            break;
7984                        case "deprecated":
7985                            hasDeprecatedTag = true;
7986                            tag = parseSimpleTag(start, factory.createJSDocDeprecatedTag, tagName, margin, indentText);
7987                            break;
7988                        case "this":
7989                            tag = parseThisTag(start, tagName, margin, indentText);
7990                            break;
7991                        case "enum":
7992                            tag = parseEnumTag(start, tagName, margin, indentText);
7993                            break;
7994                        case "arg":
7995                        case "argument":
7996                        case "param":
7997                            return parseParameterOrPropertyTag(start, tagName, PropertyLikeParse.Parameter, margin);
7998                        case "return":
7999                        case "returns":
8000                            tag = parseReturnTag(start, tagName, margin, indentText);
8001                            break;
8002                        case "template":
8003                            tag = parseTemplateTag(start, tagName, margin, indentText);
8004                            break;
8005                        case "type":
8006                            tag = parseTypeTag(start, tagName, margin, indentText);
8007                            break;
8008                        case "typedef":
8009                            tag = parseTypedefTag(start, tagName, margin, indentText);
8010                            break;
8011                        case "callback":
8012                            tag = parseCallbackTag(start, tagName, margin, indentText);
8013                            break;
8014                        case "see":
8015                            tag = parseSeeTag(start, tagName, margin, indentText);
8016                            break;
8017                        default:
8018                            tag = parseUnknownTag(start, tagName, margin, indentText);
8019                            break;
8020                    }
8021                    return tag;
8022                }
8023
8024                function parseTrailingTagComments(pos: number, end: number, margin: number, indentText: string) {
8025                    // some tags, like typedef and callback, have already parsed their comments earlier
8026                    if (!indentText) {
8027                        margin += end - pos;
8028                    }
8029                    return parseTagComments(margin, indentText.slice(margin));
8030                }
8031
8032                function parseTagComments(indent: number, initialMargin?: string): string | undefined {
8033                    const comments: string[] = [];
8034                    let state = JSDocState.BeginningOfLine;
8035                    let previousWhitespace = true;
8036                    let margin: number | undefined;
8037                    function pushComment(text: string) {
8038                        if (!margin) {
8039                            margin = indent;
8040                        }
8041                        comments.push(text);
8042                        indent += text.length;
8043                    }
8044                    if (initialMargin !== undefined) {
8045                        // jump straight to saving comments if there is some initial indentation
8046                        if (initialMargin !== "") {
8047                            pushComment(initialMargin);
8048                        }
8049                        state = JSDocState.SawAsterisk;
8050                    }
8051                    let tok = token() as JSDocSyntaxKind;
8052                    loop: while (true) {
8053                        switch (tok) {
8054                            case SyntaxKind.NewLineTrivia:
8055                                state = JSDocState.BeginningOfLine;
8056                                // don't use pushComment here because we want to keep the margin unchanged
8057                                comments.push(scanner.getTokenText());
8058                                indent = 0;
8059                                break;
8060                            case SyntaxKind.AtToken:
8061                                if (state === JSDocState.SavingBackticks || !previousWhitespace && state === JSDocState.SavingComments) {
8062                                    // @ doesn't start a new tag inside ``, and inside a comment, only after whitespace
8063                                    comments.push(scanner.getTokenText());
8064                                    break;
8065                                }
8066                                scanner.setTextPos(scanner.getTextPos() - 1);
8067                                // falls through
8068                            case SyntaxKind.EndOfFileToken:
8069                                // Done
8070                                break loop;
8071                            case SyntaxKind.WhitespaceTrivia:
8072                                if (state === JSDocState.SavingComments || state === JSDocState.SavingBackticks) {
8073                                    pushComment(scanner.getTokenText());
8074                                }
8075                                else {
8076                                    const whitespace = scanner.getTokenText();
8077                                    // if the whitespace crosses the margin, take only the whitespace that passes the margin
8078                                    if (margin !== undefined && indent + whitespace.length > margin) {
8079                                        comments.push(whitespace.slice(margin - indent));
8080                                    }
8081                                    indent += whitespace.length;
8082                                }
8083                                break;
8084                            case SyntaxKind.OpenBraceToken:
8085                                state = JSDocState.SavingComments;
8086                                if (lookAhead(() => nextTokenJSDoc() === SyntaxKind.AtToken && tokenIsIdentifierOrKeyword(nextTokenJSDoc()) && scanner.getTokenText() === "link")) {
8087                                    pushComment(scanner.getTokenText());
8088                                    nextTokenJSDoc();
8089                                    pushComment(scanner.getTokenText());
8090                                    nextTokenJSDoc();
8091                                }
8092                                pushComment(scanner.getTokenText());
8093                                break;
8094                            case SyntaxKind.BacktickToken:
8095                                if (state === JSDocState.SavingBackticks) {
8096                                    state = JSDocState.SavingComments;
8097                                }
8098                                else {
8099                                    state = JSDocState.SavingBackticks;
8100                                }
8101                                pushComment(scanner.getTokenText());
8102                                break;
8103                            case SyntaxKind.AsteriskToken:
8104                                if (state === JSDocState.BeginningOfLine) {
8105                                    // leading asterisks start recording on the *next* (non-whitespace) token
8106                                    state = JSDocState.SawAsterisk;
8107                                    indent += 1;
8108                                    break;
8109                                }
8110                                // record the * as a comment
8111                                // falls through
8112                            default:
8113                                if (state !== JSDocState.SavingBackticks) {
8114                                    state = JSDocState.SavingComments; // leading identifiers start recording as well
8115                                }
8116                                pushComment(scanner.getTokenText());
8117                                break;
8118                        }
8119                        previousWhitespace = token() === SyntaxKind.WhitespaceTrivia;
8120                        tok = nextTokenJSDoc();
8121                    }
8122
8123                    removeLeadingNewlines(comments);
8124                    removeTrailingWhitespace(comments);
8125                    return comments.length === 0 ? undefined : comments.join("");
8126                }
8127
8128                function parseUnknownTag(start: number, tagName: Identifier, indent: number, indentText: string) {
8129                    const end = getNodePos();
8130                    return finishNode(factory.createJSDocUnknownTag(tagName, parseTrailingTagComments(start, end, indent, indentText)), start, end);
8131                }
8132
8133                function addTag(tag: JSDocTag | undefined): void {
8134                    if (!tag) {
8135                        return;
8136                    }
8137                    if (!tags) {
8138                        tags = [tag];
8139                        tagsPos = tag.pos;
8140                    }
8141                    else {
8142                        tags.push(tag);
8143                    }
8144                    tagsEnd = tag.end;
8145                }
8146
8147                function tryParseTypeExpression(): JSDocTypeExpression | undefined {
8148                    skipWhitespaceOrAsterisk();
8149                    return token() === SyntaxKind.OpenBraceToken ? parseJSDocTypeExpression() : undefined;
8150                }
8151
8152                function parseBracketNameInPropertyAndParamTag(): { name: EntityName, isBracketed: boolean } {
8153                    // Looking for something like '[foo]', 'foo', '[foo.bar]' or 'foo.bar'
8154                    const isBracketed = parseOptionalJsdoc(SyntaxKind.OpenBracketToken);
8155                    if (isBracketed) {
8156                        skipWhitespace();
8157                    }
8158                    // a markdown-quoted name: `arg` is not legal jsdoc, but occurs in the wild
8159                    const isBackquoted = parseOptionalJsdoc(SyntaxKind.BacktickToken);
8160                    const name = parseJSDocEntityName();
8161                    if (isBackquoted) {
8162                        parseExpectedTokenJSDoc(SyntaxKind.BacktickToken);
8163                    }
8164                    if (isBracketed) {
8165                        skipWhitespace();
8166                        // May have an optional default, e.g. '[foo = 42]'
8167                        if (parseOptionalToken(SyntaxKind.EqualsToken)) {
8168                            parseExpression();
8169                        }
8170
8171                        parseExpected(SyntaxKind.CloseBracketToken);
8172                    }
8173
8174                    return { name, isBracketed };
8175                }
8176
8177                function isObjectOrObjectArrayTypeReference(node: TypeNode): boolean {
8178                    switch (node.kind) {
8179                        case SyntaxKind.ObjectKeyword:
8180                            return true;
8181                        case SyntaxKind.ArrayType:
8182                            return isObjectOrObjectArrayTypeReference((node as ArrayTypeNode).elementType);
8183                        default:
8184                            return isTypeReferenceNode(node) && ts.isIdentifier(node.typeName) && node.typeName.escapedText === "Object" && !node.typeArguments;
8185                    }
8186                }
8187
8188                function parseParameterOrPropertyTag(start: number, tagName: Identifier, target: PropertyLikeParse, indent: number): JSDocParameterTag | JSDocPropertyTag {
8189                    let typeExpression = tryParseTypeExpression();
8190                    let isNameFirst = !typeExpression;
8191                    skipWhitespaceOrAsterisk();
8192
8193                    const { name, isBracketed } = parseBracketNameInPropertyAndParamTag();
8194                    const indentText = skipWhitespaceOrAsterisk();
8195
8196                    if (isNameFirst) {
8197                        typeExpression = tryParseTypeExpression();
8198                    }
8199
8200                    const comment = parseTrailingTagComments(start, getNodePos(), indent, indentText);
8201
8202                    const nestedTypeLiteral = target !== PropertyLikeParse.CallbackParameter && parseNestedTypeLiteral(typeExpression, name, target, indent);
8203                    if (nestedTypeLiteral) {
8204                        typeExpression = nestedTypeLiteral;
8205                        isNameFirst = true;
8206                    }
8207                    const result = target === PropertyLikeParse.Property
8208                        ? factory.createJSDocPropertyTag(tagName, name, isBracketed, typeExpression, isNameFirst, comment)
8209                        : factory.createJSDocParameterTag(tagName, name, isBracketed, typeExpression, isNameFirst, comment);
8210                    return finishNode(result, start);
8211                }
8212
8213                function parseNestedTypeLiteral(typeExpression: JSDocTypeExpression | undefined, name: EntityName, target: PropertyLikeParse, indent: number) {
8214                    if (typeExpression && isObjectOrObjectArrayTypeReference(typeExpression.type)) {
8215                        const pos = getNodePos();
8216                        let child: JSDocPropertyLikeTag | JSDocTypeTag | false;
8217                        let children: JSDocPropertyLikeTag[] | undefined;
8218                        while (child = tryParse(() => parseChildParameterOrPropertyTag(target, indent, name))) {
8219                            if (child.kind === SyntaxKind.JSDocParameterTag || child.kind === SyntaxKind.JSDocPropertyTag) {
8220                                children = append(children, child);
8221                            }
8222                        }
8223                        if (children) {
8224                            const literal = finishNode(factory.createJSDocTypeLiteral(children, typeExpression.type.kind === SyntaxKind.ArrayType), pos);
8225                            return finishNode(factory.createJSDocTypeExpression(literal), pos);
8226                        }
8227                    }
8228                }
8229
8230                function parseReturnTag(start: number, tagName: Identifier, indent: number, indentText: string): JSDocReturnTag {
8231                    if (some(tags, isJSDocReturnTag)) {
8232                        parseErrorAt(tagName.pos, scanner.getTokenPos(), Diagnostics._0_tag_already_specified, tagName.escapedText);
8233                    }
8234
8235                    const typeExpression = tryParseTypeExpression();
8236                    const end = getNodePos();
8237                    return finishNode(factory.createJSDocReturnTag(tagName, typeExpression, parseTrailingTagComments(start, end, indent, indentText)), start, end);
8238                }
8239
8240                function parseTypeTag(start: number, tagName: Identifier, indent?: number, indentText?: string): JSDocTypeTag {
8241                    if (some(tags, isJSDocTypeTag)) {
8242                        parseErrorAt(tagName.pos, scanner.getTokenPos(), Diagnostics._0_tag_already_specified, tagName.escapedText);
8243                    }
8244
8245                    const typeExpression = parseJSDocTypeExpression(/*mayOmitBraces*/ true);
8246                    const end = getNodePos();
8247                    const comments = indent !== undefined && indentText !== undefined ? parseTrailingTagComments(start, end, indent, indentText) : undefined;
8248                    return finishNode(factory.createJSDocTypeTag(tagName, typeExpression, comments), start, end);
8249                }
8250
8251                function parseSeeTag(start: number, tagName: Identifier, indent?: number, indentText?: string): JSDocSeeTag {
8252                    const nameExpression = parseJSDocNameReference();
8253                    const end = getNodePos();
8254                    const comments = indent !== undefined && indentText !== undefined ? parseTrailingTagComments(start, end, indent, indentText) : undefined;
8255                    return finishNode(factory.createJSDocSeeTag(tagName, nameExpression, comments), start, end);
8256                }
8257
8258                function parseAuthorTag(start: number, tagName: Identifier, indent: number, indentText: string): JSDocAuthorTag {
8259                    const comments = parseAuthorNameAndEmail() + (parseTrailingTagComments(start, end, indent, indentText) || "");
8260                    return finishNode(factory.createJSDocAuthorTag(tagName, comments || undefined), start);
8261                }
8262
8263                function parseAuthorNameAndEmail(): string {
8264                    const comments: string[] = [];
8265                    let inEmail = false;
8266                    let token = scanner.getToken();
8267                    while (token !== SyntaxKind.EndOfFileToken && token !== SyntaxKind.NewLineTrivia) {
8268                        if (token === SyntaxKind.LessThanToken) {
8269                            inEmail = true;
8270                        }
8271                        else if (token === SyntaxKind.AtToken && !inEmail) {
8272                            break;
8273                        }
8274                        else if (token === SyntaxKind.GreaterThanToken && inEmail) {
8275                            comments.push(scanner.getTokenText());
8276                            scanner.setTextPos(scanner.getTokenPos() + 1);
8277                            break;
8278                        }
8279                        comments.push(scanner.getTokenText());
8280                        token = nextTokenJSDoc();
8281                    }
8282
8283                    return comments.join("");
8284                }
8285
8286                function parseImplementsTag(start: number, tagName: Identifier, margin: number, indentText: string): JSDocImplementsTag {
8287                    const className = parseExpressionWithTypeArgumentsForAugments();
8288                    const end = getNodePos();
8289                    return finishNode(factory.createJSDocImplementsTag(tagName, className, parseTrailingTagComments(start, end, margin, indentText)), start, end);
8290                }
8291
8292                function parseAugmentsTag(start: number, tagName: Identifier, margin: number, indentText: string): JSDocAugmentsTag {
8293                    const className = parseExpressionWithTypeArgumentsForAugments();
8294                    const end = getNodePos();
8295                    return finishNode(factory.createJSDocAugmentsTag(tagName, className, parseTrailingTagComments(start, end, margin, indentText)), start, end);
8296                }
8297
8298                function parseExpressionWithTypeArgumentsForAugments(): ExpressionWithTypeArguments & { expression: Identifier | PropertyAccessEntityNameExpression } {
8299                    const usedBrace = parseOptional(SyntaxKind.OpenBraceToken);
8300                    const pos = getNodePos();
8301                    const expression = parsePropertyAccessEntityNameExpression();
8302                    const typeArguments = tryParseTypeArguments();
8303                    const node = factory.createExpressionWithTypeArguments(expression, typeArguments) as ExpressionWithTypeArguments & { expression: Identifier | PropertyAccessEntityNameExpression };
8304                    const res = finishNode(node, pos);
8305                    if (usedBrace) {
8306                        parseExpected(SyntaxKind.CloseBraceToken);
8307                    }
8308                    return res;
8309                }
8310
8311                function parsePropertyAccessEntityNameExpression() {
8312                    const pos = getNodePos();
8313                    let node: Identifier | PropertyAccessEntityNameExpression = parseJSDocIdentifierName();
8314                    while (parseOptional(SyntaxKind.DotToken)) {
8315                        const name = parseJSDocIdentifierName();
8316                        node = finishNode(factory.createPropertyAccessExpression(node, name), pos) as PropertyAccessEntityNameExpression;
8317                    }
8318                    return node;
8319                }
8320
8321                function parseSimpleTag(start: number, createTag: (tagName: Identifier | undefined, comment?: string) => JSDocTag, tagName: Identifier, margin: number, indentText: string): JSDocTag {
8322                    const end = getNodePos();
8323                    return finishNode(createTag(tagName, parseTrailingTagComments(start, end, margin, indentText)), start, end);
8324                }
8325
8326                function parseThisTag(start: number, tagName: Identifier, margin: number, indentText: string): JSDocThisTag {
8327                    const typeExpression = parseJSDocTypeExpression(/*mayOmitBraces*/ true);
8328                    skipWhitespace();
8329                    const end = getNodePos();
8330                    return finishNode(factory.createJSDocThisTag(tagName, typeExpression, parseTrailingTagComments(start, end, margin, indentText)), start, end);
8331                }
8332
8333                function parseEnumTag(start: number, tagName: Identifier, margin: number, indentText: string): JSDocEnumTag {
8334                    const typeExpression = parseJSDocTypeExpression(/*mayOmitBraces*/ true);
8335                    skipWhitespace();
8336                    const end = getNodePos();
8337                    return finishNode(factory.createJSDocEnumTag(tagName, typeExpression, parseTrailingTagComments(start, end, margin, indentText)), start, end);
8338                }
8339
8340                function parseTypedefTag(start: number, tagName: Identifier, indent: number, indentText: string): JSDocTypedefTag {
8341                    let typeExpression: JSDocTypeExpression | JSDocTypeLiteral | undefined = tryParseTypeExpression();
8342                    skipWhitespaceOrAsterisk();
8343
8344                    const fullName = parseJSDocTypeNameWithNamespace();
8345                    skipWhitespace();
8346                    let comment = parseTagComments(indent);
8347
8348                    let end: number | undefined;
8349                    if (!typeExpression || isObjectOrObjectArrayTypeReference(typeExpression.type)) {
8350                        let child: JSDocTypeTag | JSDocPropertyTag | false;
8351                        let childTypeTag: JSDocTypeTag | undefined;
8352                        let jsDocPropertyTags: JSDocPropertyTag[] | undefined;
8353                        let hasChildren = false;
8354                        while (child = tryParse(() => parseChildPropertyTag(indent))) {
8355                            hasChildren = true;
8356                            if (child.kind === SyntaxKind.JSDocTypeTag) {
8357                                if (childTypeTag) {
8358                                    parseErrorAtCurrentToken(Diagnostics.A_JSDoc_typedef_comment_may_not_contain_multiple_type_tags);
8359                                    const lastError = lastOrUndefined(parseDiagnostics);
8360                                    if (lastError) {
8361                                        addRelatedInfo(
8362                                            lastError,
8363                                            createDetachedDiagnostic(fileName, 0, 0, Diagnostics.The_tag_was_first_specified_here)
8364                                        );
8365                                    }
8366                                    break;
8367                                }
8368                                else {
8369                                    childTypeTag = child;
8370                                }
8371                            }
8372                            else {
8373                                jsDocPropertyTags = append(jsDocPropertyTags, child);
8374                            }
8375                        }
8376                        if (hasChildren) {
8377                            const isArrayType = typeExpression && typeExpression.type.kind === SyntaxKind.ArrayType;
8378                            const jsdocTypeLiteral = factory.createJSDocTypeLiteral(jsDocPropertyTags, isArrayType);
8379                            typeExpression = childTypeTag && childTypeTag.typeExpression && !isObjectOrObjectArrayTypeReference(childTypeTag.typeExpression.type) ?
8380                                childTypeTag.typeExpression :
8381                                finishNode(jsdocTypeLiteral, start);
8382                            end = typeExpression.end;
8383                        }
8384                    }
8385
8386                    // Only include the characters between the name end and the next token if a comment was actually parsed out - otherwise it's just whitespace
8387                    end = end || comment !== undefined ?
8388                        getNodePos() :
8389                        (fullName ?? typeExpression ?? tagName).end;
8390
8391                    if (!comment) {
8392                        comment = parseTrailingTagComments(start, end, indent, indentText);
8393                    }
8394
8395                    const typedefTag = factory.createJSDocTypedefTag(tagName, typeExpression, fullName, comment);
8396                    return finishNode(typedefTag, start, end);
8397                }
8398
8399                function parseJSDocTypeNameWithNamespace(nested?: boolean) {
8400                    const pos = scanner.getTokenPos();
8401                    if (!tokenIsIdentifierOrKeyword(token())) {
8402                        return undefined;
8403                    }
8404                    const typeNameOrNamespaceName = parseJSDocIdentifierName();
8405                    if (parseOptional(SyntaxKind.DotToken)) {
8406                        const body = parseJSDocTypeNameWithNamespace(/*nested*/ true);
8407                        const jsDocNamespaceNode = factory.createModuleDeclaration(
8408                            /*decorators*/ undefined,
8409                            /*modifiers*/ undefined,
8410                            typeNameOrNamespaceName,
8411                            body,
8412                            nested ? NodeFlags.NestedNamespace : undefined
8413                        ) as JSDocNamespaceDeclaration;
8414                        return finishNode(jsDocNamespaceNode, pos);
8415                    }
8416
8417                    if (nested) {
8418                        typeNameOrNamespaceName.isInJSDocNamespace = true;
8419                    }
8420                    return typeNameOrNamespaceName;
8421                }
8422
8423
8424                function parseCallbackTagParameters(indent: number) {
8425                    const pos = getNodePos();
8426                    let child: JSDocParameterTag | false;
8427                    let parameters;
8428                    while (child = tryParse(() => parseChildParameterOrPropertyTag(PropertyLikeParse.CallbackParameter, indent) as JSDocParameterTag)) {
8429                        parameters = append(parameters, child);
8430                    }
8431                    return createNodeArray(parameters || [], pos);
8432                }
8433
8434                function parseCallbackTag(start: number, tagName: Identifier, indent: number, indentText: string): JSDocCallbackTag {
8435                    const fullName = parseJSDocTypeNameWithNamespace();
8436                    skipWhitespace();
8437                    let comment = parseTagComments(indent);
8438                    const parameters = parseCallbackTagParameters(indent);
8439                    const returnTag = tryParse(() => {
8440                        if (parseOptionalJsdoc(SyntaxKind.AtToken)) {
8441                            const tag = parseTag(indent);
8442                            if (tag && tag.kind === SyntaxKind.JSDocReturnTag) {
8443                                return tag as JSDocReturnTag;
8444                            }
8445                        }
8446                    });
8447                    const typeExpression = finishNode(factory.createJSDocSignature(/*typeParameters*/ undefined, parameters, returnTag), start);
8448                    const end = getNodePos();
8449                    if (!comment) {
8450                        comment = parseTrailingTagComments(start, end, indent, indentText);
8451                    }
8452                    return finishNode(factory.createJSDocCallbackTag(tagName, typeExpression, fullName, comment), start, end);
8453                }
8454
8455                function escapedTextsEqual(a: EntityName, b: EntityName): boolean {
8456                    while (!ts.isIdentifier(a) || !ts.isIdentifier(b)) {
8457                        if (!ts.isIdentifier(a) && !ts.isIdentifier(b) && a.right.escapedText === b.right.escapedText) {
8458                            a = a.left;
8459                            b = b.left;
8460                        }
8461                        else {
8462                            return false;
8463                        }
8464                    }
8465                    return a.escapedText === b.escapedText;
8466                }
8467
8468                function parseChildPropertyTag(indent: number) {
8469                    return parseChildParameterOrPropertyTag(PropertyLikeParse.Property, indent) as JSDocTypeTag | JSDocPropertyTag | false;
8470                }
8471
8472                function parseChildParameterOrPropertyTag(target: PropertyLikeParse, indent: number, name?: EntityName): JSDocTypeTag | JSDocPropertyTag | JSDocParameterTag | false {
8473                    let canParseTag = true;
8474                    let seenAsterisk = false;
8475                    while (true) {
8476                        switch (nextTokenJSDoc()) {
8477                            case SyntaxKind.AtToken:
8478                                if (canParseTag) {
8479                                    const child = tryParseChildTag(target, indent);
8480                                    if (child && (child.kind === SyntaxKind.JSDocParameterTag || child.kind === SyntaxKind.JSDocPropertyTag) &&
8481                                        target !== PropertyLikeParse.CallbackParameter &&
8482                                        name && (ts.isIdentifier(child.name) || !escapedTextsEqual(name, child.name.left))) {
8483                                        return false;
8484                                    }
8485                                    return child;
8486                                }
8487                                seenAsterisk = false;
8488                                break;
8489                            case SyntaxKind.NewLineTrivia:
8490                                canParseTag = true;
8491                                seenAsterisk = false;
8492                                break;
8493                            case SyntaxKind.AsteriskToken:
8494                                if (seenAsterisk) {
8495                                    canParseTag = false;
8496                                }
8497                                seenAsterisk = true;
8498                                break;
8499                            case SyntaxKind.Identifier:
8500                                canParseTag = false;
8501                                break;
8502                            case SyntaxKind.EndOfFileToken:
8503                                return false;
8504                        }
8505                    }
8506                }
8507
8508                function tryParseChildTag(target: PropertyLikeParse, indent: number): JSDocTypeTag | JSDocPropertyTag | JSDocParameterTag | false {
8509                    Debug.assert(token() === SyntaxKind.AtToken);
8510                    const start = scanner.getStartPos();
8511                    nextTokenJSDoc();
8512
8513                    const tagName = parseJSDocIdentifierName();
8514                    skipWhitespace();
8515                    let t: PropertyLikeParse;
8516                    switch (tagName.escapedText) {
8517                        case "type":
8518                            return target === PropertyLikeParse.Property && parseTypeTag(start, tagName);
8519                        case "prop":
8520                        case "property":
8521                            t = PropertyLikeParse.Property;
8522                            break;
8523                        case "arg":
8524                        case "argument":
8525                        case "param":
8526                            t = PropertyLikeParse.Parameter | PropertyLikeParse.CallbackParameter;
8527                            break;
8528                        default:
8529                            return false;
8530                    }
8531                    if (!(target & t)) {
8532                        return false;
8533                    }
8534                    return parseParameterOrPropertyTag(start, tagName, target, indent);
8535                }
8536
8537                function parseTemplateTagTypeParameter() {
8538                    const typeParameterPos = getNodePos();
8539                    const name = parseJSDocIdentifierName(Diagnostics.Unexpected_token_A_type_parameter_name_was_expected_without_curly_braces);
8540                    return finishNode(factory.createTypeParameterDeclaration(name, /*constraint*/ undefined, /*defaultType*/ undefined), typeParameterPos);
8541                }
8542
8543                function parseTemplateTagTypeParameters() {
8544                    const pos = getNodePos();
8545                    const typeParameters = [];
8546                    do {
8547                        skipWhitespace();
8548                        typeParameters.push(parseTemplateTagTypeParameter());
8549                        skipWhitespaceOrAsterisk();
8550                    } while (parseOptionalJsdoc(SyntaxKind.CommaToken));
8551                    return createNodeArray(typeParameters, pos);
8552                }
8553
8554                function parseTemplateTag(start: number, tagName: Identifier, indent: number, indentText: string): JSDocTemplateTag {
8555                    // The template tag looks like one of the following:
8556                    //   @template T,U,V
8557                    //   @template {Constraint} T
8558                    //
8559                    // According to the [closure docs](https://github.com/google/closure-compiler/wiki/Generic-Types#multiple-bounded-template-types):
8560                    //   > Multiple bounded generics cannot be declared on the same line. For the sake of clarity, if multiple templates share the same
8561                    //   > type bound they must be declared on separate lines.
8562                    //
8563                    // TODO: Determine whether we should enforce this in the checker.
8564                    // TODO: Consider moving the `constraint` to the first type parameter as we could then remove `getEffectiveConstraintOfTypeParameter`.
8565                    // TODO: Consider only parsing a single type parameter if there is a constraint.
8566                    const constraint = token() === SyntaxKind.OpenBraceToken ? parseJSDocTypeExpression() : undefined;
8567                    const typeParameters = parseTemplateTagTypeParameters();
8568                    const end = getNodePos();
8569                    return finishNode(factory.createJSDocTemplateTag(tagName, constraint, typeParameters, parseTrailingTagComments(start, end, indent, indentText)), start, end);
8570                }
8571
8572                function parseOptionalJsdoc(t: JSDocSyntaxKind): boolean {
8573                    if (token() === t) {
8574                        nextTokenJSDoc();
8575                        return true;
8576                    }
8577                    return false;
8578                }
8579
8580                function parseJSDocEntityName(): EntityName {
8581                    let entity: EntityName = parseJSDocIdentifierName();
8582                    if (parseOptional(SyntaxKind.OpenBracketToken)) {
8583                        parseExpected(SyntaxKind.CloseBracketToken);
8584                        // Note that y[] is accepted as an entity name, but the postfix brackets are not saved for checking.
8585                        // Technically usejsdoc.org requires them for specifying a property of a type equivalent to Array<{ x: ...}>
8586                        // but it's not worth it to enforce that restriction.
8587                    }
8588                    while (parseOptional(SyntaxKind.DotToken)) {
8589                        const name = parseJSDocIdentifierName();
8590                        if (parseOptional(SyntaxKind.OpenBracketToken)) {
8591                            parseExpected(SyntaxKind.CloseBracketToken);
8592                        }
8593                        entity = createQualifiedName(entity, name);
8594                    }
8595                    return entity;
8596                }
8597
8598                function parseJSDocIdentifierName(message?: DiagnosticMessage): Identifier {
8599                    if (!tokenIsIdentifierOrKeyword(token())) {
8600                        return createMissingNode<Identifier>(SyntaxKind.Identifier, /*reportAtCurrentPosition*/ !message, message || Diagnostics.Identifier_expected);
8601                    }
8602
8603                    identifierCount++;
8604                    const pos = scanner.getTokenPos();
8605                    const end = scanner.getTextPos();
8606                    const originalKeywordKind = token();
8607                    const text = internIdentifier(scanner.getTokenValue());
8608                    const result = finishNode(factory.createIdentifier(text, /*typeArguments*/ undefined, originalKeywordKind), pos, end);
8609                    nextTokenJSDoc();
8610                    return result;
8611                }
8612            }
8613        }
8614    }
8615
8616    namespace IncrementalParser {
8617        export function updateSourceFile(sourceFile: SourceFile, newText: string, textChangeRange: TextChangeRange, aggressiveChecks: boolean): SourceFile {
8618            aggressiveChecks = aggressiveChecks || Debug.shouldAssert(AssertionLevel.Aggressive);
8619
8620            checkChangeRange(sourceFile, newText, textChangeRange, aggressiveChecks);
8621            if (textChangeRangeIsUnchanged(textChangeRange)) {
8622                // if the text didn't change, then we can just return our current source file as-is.
8623                return sourceFile;
8624            }
8625
8626            if (sourceFile.statements.length === 0) {
8627                // If we don't have any statements in the current source file, then there's no real
8628                // way to incrementally parse.  So just do a full parse instead.
8629                return Parser.parseSourceFile(sourceFile.fileName, newText, sourceFile.languageVersion, /*syntaxCursor*/ undefined, /*setParentNodes*/ true, sourceFile.scriptKind);
8630            }
8631
8632            // Make sure we're not trying to incrementally update a source file more than once.  Once
8633            // we do an update the original source file is considered unusable from that point onwards.
8634            //
8635            // This is because we do incremental parsing in-place.  i.e. we take nodes from the old
8636            // tree and give them new positions and parents.  From that point on, trusting the old
8637            // tree at all is not possible as far too much of it may violate invariants.
8638            const incrementalSourceFile = <IncrementalNode><Node>sourceFile;
8639            Debug.assert(!incrementalSourceFile.hasBeenIncrementallyParsed);
8640            incrementalSourceFile.hasBeenIncrementallyParsed = true;
8641            Parser.fixupParentReferences(incrementalSourceFile);
8642            const oldText = sourceFile.text;
8643            const syntaxCursor = createSyntaxCursor(sourceFile);
8644
8645            // Make the actual change larger so that we know to reparse anything whose lookahead
8646            // might have intersected the change.
8647            const changeRange = extendToAffectedRange(sourceFile, textChangeRange);
8648            checkChangeRange(sourceFile, newText, changeRange, aggressiveChecks);
8649
8650            // Ensure that extending the affected range only moved the start of the change range
8651            // earlier in the file.
8652            Debug.assert(changeRange.span.start <= textChangeRange.span.start);
8653            Debug.assert(textSpanEnd(changeRange.span) === textSpanEnd(textChangeRange.span));
8654            Debug.assert(textSpanEnd(textChangeRangeNewSpan(changeRange)) === textSpanEnd(textChangeRangeNewSpan(textChangeRange)));
8655
8656            // The is the amount the nodes after the edit range need to be adjusted.  It can be
8657            // positive (if the edit added characters), negative (if the edit deleted characters)
8658            // or zero (if this was a pure overwrite with nothing added/removed).
8659            const delta = textChangeRangeNewSpan(changeRange).length - changeRange.span.length;
8660
8661            // If we added or removed characters during the edit, then we need to go and adjust all
8662            // the nodes after the edit.  Those nodes may move forward (if we inserted chars) or they
8663            // may move backward (if we deleted chars).
8664            //
8665            // Doing this helps us out in two ways.  First, it means that any nodes/tokens we want
8666            // to reuse are already at the appropriate position in the new text.  That way when we
8667            // reuse them, we don't have to figure out if they need to be adjusted.  Second, it makes
8668            // it very easy to determine if we can reuse a node.  If the node's position is at where
8669            // we are in the text, then we can reuse it.  Otherwise we can't.  If the node's position
8670            // is ahead of us, then we'll need to rescan tokens.  If the node's position is behind
8671            // us, then we'll need to skip it or crumble it as appropriate
8672            //
8673            // We will also adjust the positions of nodes that intersect the change range as well.
8674            // By doing this, we ensure that all the positions in the old tree are consistent, not
8675            // just the positions of nodes entirely before/after the change range.  By being
8676            // consistent, we can then easily map from positions to nodes in the old tree easily.
8677            //
8678            // Also, mark any syntax elements that intersect the changed span.  We know, up front,
8679            // that we cannot reuse these elements.
8680            updateTokenPositionsAndMarkElements(incrementalSourceFile,
8681                changeRange.span.start, textSpanEnd(changeRange.span), textSpanEnd(textChangeRangeNewSpan(changeRange)), delta, oldText, newText, aggressiveChecks);
8682
8683            // Now that we've set up our internal incremental state just proceed and parse the
8684            // source file in the normal fashion.  When possible the parser will retrieve and
8685            // reuse nodes from the old tree.
8686            //
8687            // Note: passing in 'true' for setNodeParents is very important.  When incrementally
8688            // parsing, we will be reusing nodes from the old tree, and placing it into new
8689            // parents.  If we don't set the parents now, we'll end up with an observably
8690            // inconsistent tree.  Setting the parents on the new tree should be very fast.  We
8691            // will immediately bail out of walking any subtrees when we can see that their parents
8692            // are already correct.
8693            const result = Parser.parseSourceFile(sourceFile.fileName, newText, sourceFile.languageVersion, syntaxCursor, /*setParentNodes*/ true, sourceFile.scriptKind);
8694            result.commentDirectives = getNewCommentDirectives(
8695                sourceFile.commentDirectives,
8696                result.commentDirectives,
8697                changeRange.span.start,
8698                textSpanEnd(changeRange.span),
8699                delta,
8700                oldText,
8701                newText,
8702                aggressiveChecks
8703            );
8704            return result;
8705        }
8706
8707        function getNewCommentDirectives(
8708            oldDirectives: CommentDirective[] | undefined,
8709            newDirectives: CommentDirective[] | undefined,
8710            changeStart: number,
8711            changeRangeOldEnd: number,
8712            delta: number,
8713            oldText: string,
8714            newText: string,
8715            aggressiveChecks: boolean
8716        ): CommentDirective[] | undefined {
8717            if (!oldDirectives) return newDirectives;
8718            let commentDirectives: CommentDirective[] | undefined;
8719            let addedNewlyScannedDirectives = false;
8720            for (const directive of oldDirectives) {
8721                const { range, type } = directive;
8722                // Range before the change
8723                if (range.end < changeStart) {
8724                    commentDirectives = append(commentDirectives, directive);
8725                }
8726                else if (range.pos > changeRangeOldEnd) {
8727                    addNewlyScannedDirectives();
8728                    // Node is entirely past the change range.  We need to move both its pos and
8729                    // end, forward or backward appropriately.
8730                    const updatedDirective: CommentDirective = {
8731                        range: { pos: range.pos + delta, end: range.end + delta },
8732                        type
8733                    };
8734                    commentDirectives = append(commentDirectives, updatedDirective);
8735                    if (aggressiveChecks) {
8736                        Debug.assert(oldText.substring(range.pos, range.end) === newText.substring(updatedDirective.range.pos, updatedDirective.range.end));
8737                    }
8738                }
8739                // Ignore ranges that fall in change range
8740            }
8741            addNewlyScannedDirectives();
8742            return commentDirectives;
8743
8744            function addNewlyScannedDirectives() {
8745                if (addedNewlyScannedDirectives) return;
8746                addedNewlyScannedDirectives = true;
8747                if (!commentDirectives) {
8748                    commentDirectives = newDirectives;
8749                }
8750                else if (newDirectives) {
8751                    commentDirectives.push(...newDirectives);
8752                }
8753            }
8754        }
8755
8756        function moveElementEntirelyPastChangeRange(element: IncrementalElement, isArray: boolean, delta: number, oldText: string, newText: string, aggressiveChecks: boolean) {
8757            if (isArray) {
8758                visitArray(<IncrementalNodeArray>element);
8759            }
8760            else {
8761                visitNode(<IncrementalNode>element);
8762            }
8763            return;
8764
8765            function visitNode(node: IncrementalNode) {
8766                let text = "";
8767                if (aggressiveChecks && shouldCheckNode(node)) {
8768                    text = oldText.substring(node.pos, node.end);
8769                }
8770
8771                // Ditch any existing LS children we may have created.  This way we can avoid
8772                // moving them forward.
8773                if (node._children) {
8774                    node._children = undefined;
8775                }
8776
8777                setTextRangePosEnd(node, node.pos + delta, node.end + delta);
8778
8779                if (aggressiveChecks && shouldCheckNode(node)) {
8780                    Debug.assert(text === newText.substring(node.pos, node.end));
8781                }
8782
8783                forEachChild(node, visitNode, visitArray);
8784                if (hasJSDocNodes(node)) {
8785                    for (const jsDocComment of node.jsDoc!) {
8786                        visitNode(<IncrementalNode><Node>jsDocComment);
8787                    }
8788                }
8789                checkNodePositions(node, aggressiveChecks);
8790            }
8791
8792            function visitArray(array: IncrementalNodeArray) {
8793                array._children = undefined;
8794                setTextRangePosEnd(array, array.pos + delta, array.end + delta);
8795
8796                for (const node of array) {
8797                    visitNode(node);
8798                }
8799            }
8800        }
8801
8802        function shouldCheckNode(node: Node) {
8803            switch (node.kind) {
8804                case SyntaxKind.StringLiteral:
8805                case SyntaxKind.NumericLiteral:
8806                case SyntaxKind.Identifier:
8807                    return true;
8808            }
8809
8810            return false;
8811        }
8812
8813        function adjustIntersectingElement(element: IncrementalElement, changeStart: number, changeRangeOldEnd: number, changeRangeNewEnd: number, delta: number) {
8814            Debug.assert(element.end >= changeStart, "Adjusting an element that was entirely before the change range");
8815            Debug.assert(element.pos <= changeRangeOldEnd, "Adjusting an element that was entirely after the change range");
8816            Debug.assert(element.pos <= element.end);
8817
8818            // We have an element that intersects the change range in some way.  It may have its
8819            // start, or its end (or both) in the changed range.  We want to adjust any part
8820            // that intersects such that the final tree is in a consistent state.  i.e. all
8821            // children have spans within the span of their parent, and all siblings are ordered
8822            // properly.
8823
8824            // We may need to update both the 'pos' and the 'end' of the element.
8825
8826            // If the 'pos' is before the start of the change, then we don't need to touch it.
8827            // If it isn't, then the 'pos' must be inside the change.  How we update it will
8828            // depend if delta is positive or negative. If delta is positive then we have
8829            // something like:
8830            //
8831            //  -------------------AAA-----------------
8832            //  -------------------BBBCCCCCCC-----------------
8833            //
8834            // In this case, we consider any node that started in the change range to still be
8835            // starting at the same position.
8836            //
8837            // however, if the delta is negative, then we instead have something like this:
8838            //
8839            //  -------------------XXXYYYYYYY-----------------
8840            //  -------------------ZZZ-----------------
8841            //
8842            // In this case, any element that started in the 'X' range will keep its position.
8843            // However any element that started after that will have their pos adjusted to be
8844            // at the end of the new range.  i.e. any node that started in the 'Y' range will
8845            // be adjusted to have their start at the end of the 'Z' range.
8846            //
8847            // The element will keep its position if possible.  Or Move backward to the new-end
8848            // if it's in the 'Y' range.
8849            const pos = Math.min(element.pos, changeRangeNewEnd);
8850
8851            // If the 'end' is after the change range, then we always adjust it by the delta
8852            // amount.  However, if the end is in the change range, then how we adjust it
8853            // will depend on if delta is positive or negative.  If delta is positive then we
8854            // have something like:
8855            //
8856            //  -------------------AAA-----------------
8857            //  -------------------BBBCCCCCCC-----------------
8858            //
8859            // In this case, we consider any node that ended inside the change range to keep its
8860            // end position.
8861            //
8862            // however, if the delta is negative, then we instead have something like this:
8863            //
8864            //  -------------------XXXYYYYYYY-----------------
8865            //  -------------------ZZZ-----------------
8866            //
8867            // In this case, any element that ended in the 'X' range will keep its position.
8868            // However any element that ended after that will have their pos adjusted to be
8869            // at the end of the new range.  i.e. any node that ended in the 'Y' range will
8870            // be adjusted to have their end at the end of the 'Z' range.
8871            const end = element.end >= changeRangeOldEnd ?
8872                // Element ends after the change range.  Always adjust the end pos.
8873                element.end + delta :
8874                // Element ends in the change range.  The element will keep its position if
8875                // possible. Or Move backward to the new-end if it's in the 'Y' range.
8876                Math.min(element.end, changeRangeNewEnd);
8877
8878            Debug.assert(pos <= end);
8879            if (element.parent) {
8880                Debug.assertGreaterThanOrEqual(pos, element.parent.pos);
8881                Debug.assertLessThanOrEqual(end, element.parent.end);
8882            }
8883
8884            setTextRangePosEnd(element, pos, end);
8885        }
8886
8887        function checkNodePositions(node: Node, aggressiveChecks: boolean) {
8888            if (aggressiveChecks) {
8889                let pos = node.pos;
8890                const visitNode = (child: Node) => {
8891                    Debug.assert(child.pos >= pos);
8892                    pos = child.end;
8893                };
8894                if (hasJSDocNodes(node)) {
8895                    for (const jsDocComment of node.jsDoc!) {
8896                        visitNode(jsDocComment);
8897                    }
8898                }
8899                forEachChild(node, visitNode);
8900                Debug.assert(pos <= node.end);
8901            }
8902        }
8903
8904        function updateTokenPositionsAndMarkElements(
8905            sourceFile: IncrementalNode,
8906            changeStart: number,
8907            changeRangeOldEnd: number,
8908            changeRangeNewEnd: number,
8909            delta: number,
8910            oldText: string,
8911            newText: string,
8912            aggressiveChecks: boolean): void {
8913
8914            visitNode(sourceFile);
8915            return;
8916
8917            function visitNode(child: IncrementalNode) {
8918                Debug.assert(child.pos <= child.end);
8919                if (child.pos > changeRangeOldEnd) {
8920                    // Node is entirely past the change range.  We need to move both its pos and
8921                    // end, forward or backward appropriately.
8922                    moveElementEntirelyPastChangeRange(child, /*isArray*/ false, delta, oldText, newText, aggressiveChecks);
8923                    return;
8924                }
8925
8926                // Check if the element intersects the change range.  If it does, then it is not
8927                // reusable.  Also, we'll need to recurse to see what constituent portions we may
8928                // be able to use.
8929                const fullEnd = child.end;
8930                if (fullEnd >= changeStart) {
8931                    child.intersectsChange = true;
8932                    child._children = undefined;
8933
8934                    // Adjust the pos or end (or both) of the intersecting element accordingly.
8935                    adjustIntersectingElement(child, changeStart, changeRangeOldEnd, changeRangeNewEnd, delta);
8936                    forEachChild(child, visitNode, visitArray);
8937                    if (hasJSDocNodes(child)) {
8938                        for (const jsDocComment of child.jsDoc!) {
8939                            visitNode(<IncrementalNode><Node>jsDocComment);
8940                        }
8941                    }
8942                    checkNodePositions(child, aggressiveChecks);
8943                    return;
8944                }
8945
8946                // Otherwise, the node is entirely before the change range.  No need to do anything with it.
8947                Debug.assert(fullEnd < changeStart);
8948            }
8949
8950            function visitArray(array: IncrementalNodeArray) {
8951                Debug.assert(array.pos <= array.end);
8952                if (array.pos > changeRangeOldEnd) {
8953                    // Array is entirely after the change range.  We need to move it, and move any of
8954                    // its children.
8955                    moveElementEntirelyPastChangeRange(array, /*isArray*/ true, delta, oldText, newText, aggressiveChecks);
8956                    return;
8957                }
8958
8959                // Check if the element intersects the change range.  If it does, then it is not
8960                // reusable.  Also, we'll need to recurse to see what constituent portions we may
8961                // be able to use.
8962                const fullEnd = array.end;
8963                if (fullEnd >= changeStart) {
8964                    array.intersectsChange = true;
8965                    array._children = undefined;
8966
8967                    // Adjust the pos or end (or both) of the intersecting array accordingly.
8968                    adjustIntersectingElement(array, changeStart, changeRangeOldEnd, changeRangeNewEnd, delta);
8969                    for (const node of array) {
8970                        if (!node.virtual) {
8971                            visitNode(node);
8972                        }
8973                    }
8974                    return;
8975                }
8976
8977                // Otherwise, the array is entirely before the change range.  No need to do anything with it.
8978                Debug.assert(fullEnd < changeStart);
8979            }
8980        }
8981
8982        function extendToAffectedRange(sourceFile: SourceFile, changeRange: TextChangeRange): TextChangeRange {
8983            // Consider the following code:
8984            //      void foo() { /; }
8985            //
8986            // If the text changes with an insertion of / just before the semicolon then we end up with:
8987            //      void foo() { //; }
8988            //
8989            // If we were to just use the changeRange a is, then we would not rescan the { token
8990            // (as it does not intersect the actual original change range).  Because an edit may
8991            // change the token touching it, we actually need to look back *at least* one token so
8992            // that the prior token sees that change.
8993            const maxLookahead = 1;
8994
8995            let start = changeRange.span.start;
8996
8997            // the first iteration aligns us with the change start. subsequent iteration move us to
8998            // the left by maxLookahead tokens.  We only need to do this as long as we're not at the
8999            // start of the tree.
9000            for (let i = 0; start > 0 && i <= maxLookahead; i++) {
9001                const nearestNode = findNearestNodeStartingBeforeOrAtPosition(sourceFile, start);
9002                Debug.assert(nearestNode.pos <= start);
9003                const position = nearestNode.pos;
9004
9005                start = Math.max(0, position - 1);
9006            }
9007
9008            const finalSpan = createTextSpanFromBounds(start, textSpanEnd(changeRange.span));
9009            const finalLength = changeRange.newLength + (changeRange.span.start - start);
9010
9011            return createTextChangeRange(finalSpan, finalLength);
9012        }
9013
9014        function findNearestNodeStartingBeforeOrAtPosition(sourceFile: SourceFile, position: number): Node {
9015            let bestResult: Node = sourceFile;
9016            let lastNodeEntirelyBeforePosition: Node | undefined;
9017
9018            forEachChild(sourceFile, visit);
9019
9020            if (lastNodeEntirelyBeforePosition) {
9021                const lastChildOfLastEntireNodeBeforePosition = getLastDescendant(lastNodeEntirelyBeforePosition);
9022                if (lastChildOfLastEntireNodeBeforePosition.pos > bestResult.pos) {
9023                    bestResult = lastChildOfLastEntireNodeBeforePosition;
9024                }
9025            }
9026
9027            return bestResult;
9028
9029            function getLastDescendant(node: Node): Node {
9030                while (true) {
9031                    const lastChild = getLastChild(node);
9032                    if (lastChild) {
9033                        node = lastChild;
9034                    }
9035                    else {
9036                        return node;
9037                    }
9038                }
9039            }
9040
9041            function visit(child: Node) {
9042                if (nodeIsMissing(child)) {
9043                    // Missing nodes are effectively invisible to us.  We never even consider them
9044                    // When trying to find the nearest node before us.
9045                    return;
9046                }
9047
9048                // If the child intersects this position, then this node is currently the nearest
9049                // node that starts before the position.
9050                if (child.pos <= position) {
9051                    if (child.pos >= bestResult.pos) {
9052                        // This node starts before the position, and is closer to the position than
9053                        // the previous best node we found.  It is now the new best node.
9054                        bestResult = child;
9055                    }
9056
9057                    // Now, the node may overlap the position, or it may end entirely before the
9058                    // position.  If it overlaps with the position, then either it, or one of its
9059                    // children must be the nearest node before the position.  So we can just
9060                    // recurse into this child to see if we can find something better.
9061                    if (position < child.end) {
9062                        // The nearest node is either this child, or one of the children inside
9063                        // of it.  We've already marked this child as the best so far.  Recurse
9064                        // in case one of the children is better.
9065                        forEachChild(child, visit);
9066
9067                        // Once we look at the children of this node, then there's no need to
9068                        // continue any further.
9069                        return true;
9070                    }
9071                    else {
9072                        Debug.assert(child.end <= position);
9073                        // The child ends entirely before this position.  Say you have the following
9074                        // (where $ is the position)
9075                        //
9076                        //      <complex expr 1> ? <complex expr 2> $ : <...> <...>
9077                        //
9078                        // We would want to find the nearest preceding node in "complex expr 2".
9079                        // To support that, we keep track of this node, and once we're done searching
9080                        // for a best node, we recurse down this node to see if we can find a good
9081                        // result in it.
9082                        //
9083                        // This approach allows us to quickly skip over nodes that are entirely
9084                        // before the position, while still allowing us to find any nodes in the
9085                        // last one that might be what we want.
9086                        lastNodeEntirelyBeforePosition = child;
9087                    }
9088                }
9089                else {
9090                    Debug.assert(child.pos > position);
9091                    // We're now at a node that is entirely past the position we're searching for.
9092                    // This node (and all following nodes) could never contribute to the result,
9093                    // so just skip them by returning 'true' here.
9094                    return true;
9095                }
9096            }
9097        }
9098
9099        function checkChangeRange(sourceFile: SourceFile, newText: string, textChangeRange: TextChangeRange, aggressiveChecks: boolean) {
9100            const oldText = sourceFile.text;
9101            if (textChangeRange) {
9102                Debug.assert((oldText.length - textChangeRange.span.length + textChangeRange.newLength) === newText.length);
9103
9104                if (aggressiveChecks || Debug.shouldAssert(AssertionLevel.VeryAggressive)) {
9105                    const oldTextPrefix = oldText.substr(0, textChangeRange.span.start);
9106                    const newTextPrefix = newText.substr(0, textChangeRange.span.start);
9107                    Debug.assert(oldTextPrefix === newTextPrefix);
9108
9109                    const oldTextSuffix = oldText.substring(textSpanEnd(textChangeRange.span), oldText.length);
9110                    const newTextSuffix = newText.substring(textSpanEnd(textChangeRangeNewSpan(textChangeRange)), newText.length);
9111                    Debug.assert(oldTextSuffix === newTextSuffix);
9112                }
9113            }
9114        }
9115
9116        interface IncrementalElement extends ReadonlyTextRange {
9117            readonly parent: Node;
9118            intersectsChange: boolean;
9119            length?: number;
9120            _children: Node[] | undefined;
9121        }
9122
9123        export interface IncrementalNode extends Node, IncrementalElement {
9124            hasBeenIncrementallyParsed: boolean;
9125        }
9126
9127        interface IncrementalNodeArray extends NodeArray<IncrementalNode>, IncrementalElement {
9128            length: number;
9129        }
9130
9131        // Allows finding nodes in the source file at a certain position in an efficient manner.
9132        // The implementation takes advantage of the calling pattern it knows the parser will
9133        // make in order to optimize finding nodes as quickly as possible.
9134        export interface SyntaxCursor {
9135            currentNode(position: number): IncrementalNode;
9136        }
9137
9138        export function createSyntaxCursor(sourceFile: SourceFile): SyntaxCursor {
9139            let currentArray: NodeArray<Node> = sourceFile.statements;
9140            let currentArrayIndex = 0;
9141
9142            Debug.assert(currentArrayIndex < currentArray.length);
9143            let current = currentArray[currentArrayIndex];
9144            let lastQueriedPosition = InvalidPosition.Value;
9145
9146            return {
9147                currentNode(position: number) {
9148                    // Only compute the current node if the position is different than the last time
9149                    // we were asked.  The parser commonly asks for the node at the same position
9150                    // twice.  Once to know if can read an appropriate list element at a certain point,
9151                    // and then to actually read and consume the node.
9152                    if (position !== lastQueriedPosition) {
9153                        // Much of the time the parser will need the very next node in the array that
9154                        // we just returned a node from.So just simply check for that case and move
9155                        // forward in the array instead of searching for the node again.
9156                        if (current && current.end === position && currentArrayIndex < (currentArray.length - 1)) {
9157                            currentArrayIndex++;
9158                            current = currentArray[currentArrayIndex];
9159                        }
9160
9161                        // If we don't have a node, or the node we have isn't in the right position,
9162                        // then try to find a viable node at the position requested.
9163                        if (!current || current.pos !== position) {
9164                            findHighestListElementThatStartsAtPosition(position);
9165                        }
9166                    }
9167
9168                    // Cache this query so that we don't do any extra work if the parser calls back
9169                    // into us.  Note: this is very common as the parser will make pairs of calls like
9170                    // 'isListElement -> parseListElement'.  If we were unable to find a node when
9171                    // called with 'isListElement', we don't want to redo the work when parseListElement
9172                    // is called immediately after.
9173                    lastQueriedPosition = position;
9174
9175                    // Either we don'd have a node, or we have a node at the position being asked for.
9176                    Debug.assert(!current || current.pos === position);
9177                    return <IncrementalNode>current;
9178                }
9179            };
9180
9181            // Finds the highest element in the tree we can find that starts at the provided position.
9182            // The element must be a direct child of some node list in the tree.  This way after we
9183            // return it, we can easily return its next sibling in the list.
9184            function findHighestListElementThatStartsAtPosition(position: number) {
9185                // Clear out any cached state about the last node we found.
9186                currentArray = undefined!;
9187                currentArrayIndex = InvalidPosition.Value;
9188                current = undefined!;
9189
9190                // Recurse into the source file to find the highest node at this position.
9191                forEachChild(sourceFile, visitNode, visitArray);
9192                return;
9193
9194                function visitNode(node: Node) {
9195                    if (position >= node.pos && position < node.end) {
9196                        // Position was within this node.  Keep searching deeper to find the node.
9197                        forEachChild(node, visitNode, visitArray);
9198
9199                        // don't proceed any further in the search.
9200                        return true;
9201                    }
9202
9203                    // position wasn't in this node, have to keep searching.
9204                    return false;
9205                }
9206
9207                function visitArray(array: NodeArray<Node>) {
9208                    if (position >= array.pos && position < array.end) {
9209                        // position was in this array.  Search through this array to see if we find a
9210                        // viable element.
9211                        for (let i = 0; i < array.length; i++) {
9212                            const child = array[i];
9213                            if (child) {
9214                                if (child.pos === position) {
9215                                    // Found the right node.  We're done.
9216                                    currentArray = array;
9217                                    currentArrayIndex = i;
9218                                    current = child;
9219                                    return true;
9220                                }
9221                                else {
9222                                    if (child.pos < position && position < child.end) {
9223                                        // Position in somewhere within this child.  Search in it and
9224                                        // stop searching in this array.
9225                                        forEachChild(child, visitNode, visitArray);
9226                                        return true;
9227                                    }
9228                                }
9229                            }
9230                        }
9231                    }
9232
9233                    // position wasn't in this array, have to keep searching.
9234                    return false;
9235                }
9236            }
9237        }
9238
9239        const enum InvalidPosition {
9240            Value = -1
9241        }
9242    }
9243
9244    /** @internal */
9245    export function isDeclarationFileName(fileName: string): boolean {
9246        return fileExtensionIs(fileName, Extension.Dts) || fileExtensionIs(fileName, Extension.Dets);
9247    }
9248
9249    /*@internal*/
9250    export interface PragmaContext {
9251        languageVersion: ScriptTarget;
9252        pragmas?: PragmaMap;
9253        checkJsDirective?: CheckJsDirective;
9254        referencedFiles: FileReference[];
9255        typeReferenceDirectives: FileReference[];
9256        libReferenceDirectives: FileReference[];
9257        amdDependencies: AmdDependency[];
9258        hasNoDefaultLib?: boolean;
9259        moduleName?: string;
9260    }
9261
9262    /*@internal*/
9263    export function processCommentPragmas(context: PragmaContext, sourceText: string): void {
9264        const pragmas: PragmaPseudoMapEntry[] = [];
9265
9266        for (const range of getLeadingCommentRanges(sourceText, 0) || emptyArray) {
9267            const comment = sourceText.substring(range.pos, range.end);
9268            extractPragmas(pragmas, range, comment);
9269        }
9270
9271        context.pragmas = new Map() as PragmaMap;
9272        for (const pragma of pragmas) {
9273            if (context.pragmas.has(pragma.name)) {
9274                const currentValue = context.pragmas.get(pragma.name);
9275                if (currentValue instanceof Array) {
9276                    currentValue.push(pragma.args);
9277                }
9278                else {
9279                    context.pragmas.set(pragma.name, [currentValue, pragma.args]);
9280                }
9281                continue;
9282            }
9283            context.pragmas.set(pragma.name, pragma.args);
9284        }
9285    }
9286
9287    /*@internal*/
9288    type PragmaDiagnosticReporter = (pos: number, length: number, message: DiagnosticMessage) => void;
9289
9290    /*@internal*/
9291    export function processPragmasIntoFields(context: PragmaContext, reportDiagnostic: PragmaDiagnosticReporter): void {
9292        context.checkJsDirective = undefined;
9293        context.referencedFiles = [];
9294        context.typeReferenceDirectives = [];
9295        context.libReferenceDirectives = [];
9296        context.amdDependencies = [];
9297        context.hasNoDefaultLib = false;
9298        context.pragmas!.forEach((entryOrList, key) => { // TODO: GH#18217
9299            // TODO: The below should be strongly type-guarded and not need casts/explicit annotations, since entryOrList is related to
9300            // key and key is constrained to a union; but it's not (see GH#21483 for at least partial fix) :(
9301            switch (key) {
9302                case "reference": {
9303                    const referencedFiles = context.referencedFiles;
9304                    const typeReferenceDirectives = context.typeReferenceDirectives;
9305                    const libReferenceDirectives = context.libReferenceDirectives;
9306                    forEach(toArray(entryOrList) as PragmaPseudoMap["reference"][], arg => {
9307                        const { types, lib, path } = arg.arguments;
9308                        if (arg.arguments["no-default-lib"]) {
9309                            context.hasNoDefaultLib = true;
9310                        }
9311                        else if (types) {
9312                            typeReferenceDirectives.push({ pos: types.pos, end: types.end, fileName: types.value });
9313                        }
9314                        else if (lib) {
9315                            libReferenceDirectives.push({ pos: lib.pos, end: lib.end, fileName: lib.value });
9316                        }
9317                        else if (path) {
9318                            referencedFiles.push({ pos: path.pos, end: path.end, fileName: path.value });
9319                        }
9320                        else {
9321                            reportDiagnostic(arg.range.pos, arg.range.end - arg.range.pos, Diagnostics.Invalid_reference_directive_syntax);
9322                        }
9323                    });
9324                    break;
9325                }
9326                case "amd-dependency": {
9327                    context.amdDependencies = map(
9328                        toArray(entryOrList) as PragmaPseudoMap["amd-dependency"][],
9329                        x => ({ name: x.arguments.name, path: x.arguments.path }));
9330                    break;
9331                }
9332                case "amd-module": {
9333                    if (entryOrList instanceof Array) {
9334                        for (const entry of entryOrList) {
9335                            if (context.moduleName) {
9336                                // TODO: It's probably fine to issue this diagnostic on all instances of the pragma
9337                                reportDiagnostic(entry.range.pos, entry.range.end - entry.range.pos, Diagnostics.An_AMD_module_cannot_have_multiple_name_assignments);
9338                            }
9339                            context.moduleName = (entry as PragmaPseudoMap["amd-module"]).arguments.name;
9340                        }
9341                    }
9342                    else {
9343                        context.moduleName = (entryOrList as PragmaPseudoMap["amd-module"]).arguments.name;
9344                    }
9345                    break;
9346                }
9347                case "ts-nocheck":
9348                case "ts-check": {
9349                    // _last_ of either nocheck or check in a file is the "winner"
9350                    forEach(toArray(entryOrList), entry => {
9351                        if (!context.checkJsDirective || entry.range.pos > context.checkJsDirective.pos) {
9352                            context.checkJsDirective = {
9353                                enabled: key === "ts-check",
9354                                end: entry.range.end,
9355                                pos: entry.range.pos
9356                            };
9357                        }
9358                    });
9359                    break;
9360                }
9361                case "jsx":
9362                case "jsxfrag":
9363                case "jsximportsource":
9364                case "jsxruntime":
9365                    return; // Accessed directly
9366                default: Debug.fail("Unhandled pragma kind"); // Can this be made into an assertNever in the future?
9367            }
9368        });
9369    }
9370
9371    const namedArgRegExCache = new Map<string, RegExp>();
9372    function getNamedArgRegEx(name: string): RegExp {
9373        if (namedArgRegExCache.has(name)) {
9374            return namedArgRegExCache.get(name)!;
9375        }
9376        const result = new RegExp(`(\\s${name}\\s*=\\s*)('|")(.+?)\\2`, "im");
9377        namedArgRegExCache.set(name, result);
9378        return result;
9379    }
9380
9381    const tripleSlashXMLCommentStartRegEx = /^\/\/\/\s*<(\S+)\s.*?\/>/im;
9382    const singleLinePragmaRegEx = /^\/\/\/?\s*@(\S+)\s*(.*)\s*$/im;
9383    function extractPragmas(pragmas: PragmaPseudoMapEntry[], range: CommentRange, text: string) {
9384        const tripleSlash = range.kind === SyntaxKind.SingleLineCommentTrivia && tripleSlashXMLCommentStartRegEx.exec(text);
9385        if (tripleSlash) {
9386            const name = tripleSlash[1].toLowerCase() as keyof PragmaPseudoMap; // Technically unsafe cast, but we do it so the below check to make it safe typechecks
9387            const pragma = commentPragmas[name] as PragmaDefinition;
9388            if (!pragma || !(pragma.kind! & PragmaKindFlags.TripleSlashXML)) {
9389                return;
9390            }
9391            if (pragma.args) {
9392                const argument: {[index: string]: string | {value: string, pos: number, end: number}} = {};
9393                for (const arg of pragma.args) {
9394                    const matcher = getNamedArgRegEx(arg.name);
9395                    const matchResult = matcher.exec(text);
9396                    if (!matchResult && !arg.optional) {
9397                        return; // Missing required argument, don't parse
9398                    }
9399                    else if (matchResult) {
9400                        if (arg.captureSpan) {
9401                            const startPos = range.pos + matchResult.index + matchResult[1].length + matchResult[2].length;
9402                            argument[arg.name] = {
9403                                value: matchResult[3],
9404                                pos: startPos,
9405                                end: startPos + matchResult[3].length
9406                            };
9407                        }
9408                        else {
9409                            argument[arg.name] = matchResult[3];
9410                        }
9411                    }
9412                }
9413                pragmas.push({ name, args: { arguments: argument, range } } as PragmaPseudoMapEntry);
9414            }
9415            else {
9416                pragmas.push({ name, args: { arguments: {}, range } } as PragmaPseudoMapEntry);
9417            }
9418            return;
9419        }
9420
9421        const singleLine = range.kind === SyntaxKind.SingleLineCommentTrivia && singleLinePragmaRegEx.exec(text);
9422        if (singleLine) {
9423            return addPragmaForMatch(pragmas, range, PragmaKindFlags.SingleLine, singleLine);
9424        }
9425
9426        if (range.kind === SyntaxKind.MultiLineCommentTrivia) {
9427            const multiLinePragmaRegEx = /\s*@(\S+)\s*(.*)\s*$/gim; // Defined inline since it uses the "g" flag, which keeps a persistent index (for iterating)
9428            let multiLineMatch: RegExpExecArray | null;
9429            while (multiLineMatch = multiLinePragmaRegEx.exec(text)) {
9430                addPragmaForMatch(pragmas, range, PragmaKindFlags.MultiLine, multiLineMatch);
9431            }
9432        }
9433    }
9434
9435    function addPragmaForMatch(pragmas: PragmaPseudoMapEntry[], range: CommentRange, kind: PragmaKindFlags, match: RegExpExecArray) {
9436        if (!match) return;
9437        const name = match[1].toLowerCase() as keyof PragmaPseudoMap; // Technically unsafe cast, but we do it so they below check to make it safe typechecks
9438        const pragma = commentPragmas[name] as PragmaDefinition;
9439        if (!pragma || !(pragma.kind! & kind)) {
9440            return;
9441        }
9442        const args = match[2]; // Split on spaces and match up positionally with definition
9443        const argument = getNamedPragmaArguments(pragma, args);
9444        if (argument === "fail") return; // Missing required argument, fail to parse it
9445        pragmas.push({ name, args: { arguments: argument, range } } as PragmaPseudoMapEntry);
9446        return;
9447    }
9448
9449    function getNamedPragmaArguments(pragma: PragmaDefinition, text: string | undefined): {[index: string]: string} | "fail" {
9450        if (!text) return {};
9451        if (!pragma.args) return {};
9452        const args = text.split(/\s+/);
9453        const argMap: {[index: string]: string} = {};
9454        for (let i = 0; i < pragma.args.length; i++) {
9455            const argument = pragma.args[i];
9456            if (!args[i] && !argument.optional) {
9457                return "fail";
9458            }
9459            if (argument.captureSpan) {
9460                return Debug.fail("Capture spans not yet implemented for non-xml pragmas");
9461            }
9462            argMap[argument.name] = args[i];
9463        }
9464        return argMap;
9465    }
9466
9467    /** @internal */
9468    export function tagNamesAreEquivalent(lhs: JsxTagNameExpression, rhs: JsxTagNameExpression): boolean {
9469        if (lhs.kind !== rhs.kind) {
9470            return false;
9471        }
9472
9473        if (lhs.kind === SyntaxKind.Identifier) {
9474            return lhs.escapedText === (<Identifier>rhs).escapedText;
9475        }
9476
9477        if (lhs.kind === SyntaxKind.ThisKeyword) {
9478            return true;
9479        }
9480
9481        // If we are at this statement then we must have PropertyAccessExpression and because tag name in Jsx element can only
9482        // take forms of JsxTagNameExpression which includes an identifier, "this" expression, or another propertyAccessExpression
9483        // it is safe to case the expression property as such. See parseJsxElementName for how we parse tag name in Jsx element
9484        return (<PropertyAccessExpression>lhs).name.escapedText === (<PropertyAccessExpression>rhs).name.escapedText &&
9485            tagNamesAreEquivalent((<PropertyAccessExpression>lhs).expression as JsxTagNameExpression, (<PropertyAccessExpression>rhs).expression as JsxTagNameExpression);
9486    }
9487}
9488