• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1namespace ts {
2    let nextAutoGenerateId = 0;
3
4    /* @internal */
5    export const enum NodeFactoryFlags {
6        None = 0,
7        // Disables the parenthesizer rules for the factory.
8        NoParenthesizerRules = 1 << 0,
9        // Disables the node converters for the factory.
10        NoNodeConverters = 1 << 1,
11        // Ensures new `PropertyAccessExpression` nodes are created with the `NoIndentation` emit flag set.
12        NoIndentationOnFreshPropertyAccess = 1 << 2,
13        // Do not set an `original` pointer when updating a node.
14        NoOriginalNode = 1 << 3,
15    }
16
17    /**
18     * Creates a `NodeFactory` that can be used to create and update a syntax tree.
19     * @param flags Flags that control factory behavior.
20     * @param baseFactory A `BaseNodeFactory` used to create the base `Node` objects.
21     */
22    /* @internal */
23    export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNodeFactory): NodeFactory {
24        const update = flags & NodeFactoryFlags.NoOriginalNode ? updateWithoutOriginal : updateWithOriginal;
25
26        // Lazily load the parenthesizer, node converters, and some factory methods until they are used.
27        const parenthesizerRules = memoize(() => flags & NodeFactoryFlags.NoParenthesizerRules ? nullParenthesizerRules : createParenthesizerRules(factory));
28        const converters = memoize(() => flags & NodeFactoryFlags.NoNodeConverters ? nullNodeConverters : createNodeConverters(factory));
29
30        // lazy initializaton of common operator factories
31        const getBinaryCreateFunction = memoizeOne((operator: BinaryOperator) => (left: Expression, right: Expression) => createBinaryExpression(left, operator, right));
32        const getPrefixUnaryCreateFunction = memoizeOne((operator: PrefixUnaryOperator) => (operand: Expression) => createPrefixUnaryExpression(operator, operand));
33        const getPostfixUnaryCreateFunction = memoizeOne((operator: PostfixUnaryOperator) => (operand: Expression) => createPostfixUnaryExpression(operand, operator));
34        const getJSDocPrimaryTypeCreateFunction = memoizeOne(<T extends JSDocType>(kind: T["kind"]) => () => createJSDocPrimaryTypeWorker(kind));
35        const getJSDocUnaryTypeCreateFunction = memoizeOne(<T extends JSDocType & { readonly type: TypeNode | undefined; }>(kind: T["kind"]) => (type: T["type"]) => createJSDocUnaryTypeWorker<T>(kind, type));
36        const getJSDocUnaryTypeUpdateFunction = memoizeOne(<T extends JSDocType & { readonly type: TypeNode | undefined; }>(kind: T["kind"]) => (node: T, type: T["type"]) => updateJSDocUnaryTypeWorker<T>(kind, node, type));
37        const getJSDocPrePostfixUnaryTypeCreateFunction = memoizeOne(<T extends JSDocType & { readonly type: TypeNode | undefined; readonly postfix: boolean; }>(kind: T["kind"]) => (type: T["type"], postfix?: boolean) => createJSDocPrePostfixUnaryTypeWorker<T>(kind, type, postfix));
38        const getJSDocPrePostfixUnaryTypeUpdateFunction = memoizeOne(<T extends JSDocType & { readonly type: TypeNode | undefined; readonly postfix: boolean; }>(kind: T["kind"]) => (node: T, type: T["type"]) => updateJSDocPrePostfixUnaryTypeWorker<T>(kind, node, type));
39        const getJSDocSimpleTagCreateFunction = memoizeOne(<T extends JSDocTag>(kind: T["kind"]) => (tagName: Identifier | undefined, comment?: NodeArray<JSDocComment>) => createJSDocSimpleTagWorker(kind, tagName, comment));
40        const getJSDocSimpleTagUpdateFunction = memoizeOne(<T extends JSDocTag>(kind: T["kind"]) => (node: T, tagName: Identifier | undefined, comment?: NodeArray<JSDocComment>) => updateJSDocSimpleTagWorker(kind, node, tagName, comment));
41        const getJSDocTypeLikeTagCreateFunction = memoizeOne(<T extends JSDocTag & { typeExpression?: JSDocTypeExpression }>(kind: T["kind"]) => (tagName: Identifier | undefined, typeExpression?: JSDocTypeExpression, comment?: NodeArray<JSDocComment>) => createJSDocTypeLikeTagWorker(kind, tagName, typeExpression, comment));
42        const getJSDocTypeLikeTagUpdateFunction = memoizeOne(<T extends JSDocTag & { typeExpression?: JSDocTypeExpression }>(kind: T["kind"]) => (node: T, tagName: Identifier | undefined, typeExpression?: JSDocTypeExpression, comment?: NodeArray<JSDocComment>) => updateJSDocTypeLikeTagWorker(kind, node, tagName, typeExpression, comment));
43
44        const factory: NodeFactory = {
45            get parenthesizer() { return parenthesizerRules(); },
46            get converters() { return converters(); },
47            baseFactory,
48            flags,
49            createNodeArray,
50            createNumericLiteral,
51            createBigIntLiteral,
52            createStringLiteral,
53            createStringLiteralFromNode,
54            createRegularExpressionLiteral,
55            createLiteralLikeNode,
56            createIdentifier,
57            updateIdentifier,
58            createTempVariable,
59            createLoopVariable,
60            createUniqueName,
61            getGeneratedNameForNode,
62            createPrivateIdentifier,
63            createUniquePrivateName,
64            getGeneratedPrivateNameForNode,
65            createToken,
66            createSuper,
67            createThis,
68            createNull,
69            createTrue,
70            createFalse,
71            createModifier,
72            createModifiersFromModifierFlags,
73            createQualifiedName,
74            updateQualifiedName,
75            createComputedPropertyName,
76            updateComputedPropertyName,
77            createTypeParameterDeclaration,
78            updateTypeParameterDeclaration,
79            createParameterDeclaration,
80            updateParameterDeclaration,
81            createDecorator,
82            updateDecorator,
83            createPropertySignature,
84            updatePropertySignature,
85            createPropertyDeclaration,
86            updatePropertyDeclaration,
87            createMethodSignature,
88            updateMethodSignature,
89            createMethodDeclaration,
90            updateMethodDeclaration,
91            createConstructorDeclaration,
92            updateConstructorDeclaration,
93            createGetAccessorDeclaration,
94            updateGetAccessorDeclaration,
95            createSetAccessorDeclaration,
96            updateSetAccessorDeclaration,
97            createCallSignature,
98            updateCallSignature,
99            createConstructSignature,
100            updateConstructSignature,
101            createIndexSignature,
102            updateIndexSignature,
103            createClassStaticBlockDeclaration,
104            updateClassStaticBlockDeclaration,
105            createTemplateLiteralTypeSpan,
106            updateTemplateLiteralTypeSpan,
107            createKeywordTypeNode,
108            createTypePredicateNode,
109            updateTypePredicateNode,
110            createTypeReferenceNode,
111            updateTypeReferenceNode,
112            createFunctionTypeNode,
113            updateFunctionTypeNode,
114            createConstructorTypeNode,
115            updateConstructorTypeNode,
116            createTypeQueryNode,
117            updateTypeQueryNode,
118            createTypeLiteralNode,
119            updateTypeLiteralNode,
120            createArrayTypeNode,
121            updateArrayTypeNode,
122            createTupleTypeNode,
123            updateTupleTypeNode,
124            createNamedTupleMember,
125            updateNamedTupleMember,
126            createOptionalTypeNode,
127            updateOptionalTypeNode,
128            createRestTypeNode,
129            updateRestTypeNode,
130            createUnionTypeNode,
131            updateUnionTypeNode,
132            createIntersectionTypeNode,
133            updateIntersectionTypeNode,
134            createConditionalTypeNode,
135            updateConditionalTypeNode,
136            createInferTypeNode,
137            updateInferTypeNode,
138            createImportTypeNode,
139            updateImportTypeNode,
140            createParenthesizedType,
141            updateParenthesizedType,
142            createThisTypeNode,
143            createTypeOperatorNode,
144            updateTypeOperatorNode,
145            createIndexedAccessTypeNode,
146            updateIndexedAccessTypeNode,
147            createMappedTypeNode,
148            updateMappedTypeNode,
149            createLiteralTypeNode,
150            updateLiteralTypeNode,
151            createTemplateLiteralType,
152            updateTemplateLiteralType,
153            createObjectBindingPattern,
154            updateObjectBindingPattern,
155            createArrayBindingPattern,
156            updateArrayBindingPattern,
157            createBindingElement,
158            updateBindingElement,
159            createArrayLiteralExpression,
160            updateArrayLiteralExpression,
161            createObjectLiteralExpression,
162            updateObjectLiteralExpression,
163            createPropertyAccessExpression: flags & NodeFactoryFlags.NoIndentationOnFreshPropertyAccess ?
164                (expression, name) => setEmitFlags(createPropertyAccessExpression(expression, name), EmitFlags.NoIndentation) :
165                createPropertyAccessExpression,
166            updatePropertyAccessExpression,
167            createPropertyAccessChain: flags & NodeFactoryFlags.NoIndentationOnFreshPropertyAccess ?
168                (expression, questionDotToken, name) => setEmitFlags(createPropertyAccessChain(expression, questionDotToken, name), EmitFlags.NoIndentation) :
169                createPropertyAccessChain,
170            updatePropertyAccessChain,
171            createElementAccessExpression,
172            updateElementAccessExpression,
173            createElementAccessChain,
174            updateElementAccessChain,
175            createCallExpression,
176            updateCallExpression,
177            createCallChain,
178            updateCallChain,
179            createNewExpression,
180            updateNewExpression,
181            createTaggedTemplateExpression,
182            updateTaggedTemplateExpression,
183            createTypeAssertion,
184            updateTypeAssertion,
185            createParenthesizedExpression,
186            updateParenthesizedExpression,
187            createFunctionExpression,
188            updateFunctionExpression,
189            createEtsComponentExpression,
190            updateEtsComponentExpression,
191            createArrowFunction,
192            updateArrowFunction,
193            createDeleteExpression,
194            updateDeleteExpression,
195            createTypeOfExpression,
196            updateTypeOfExpression,
197            createVoidExpression,
198            updateVoidExpression,
199            createAwaitExpression,
200            updateAwaitExpression,
201            createPrefixUnaryExpression,
202            updatePrefixUnaryExpression,
203            createPostfixUnaryExpression,
204            updatePostfixUnaryExpression,
205            createBinaryExpression,
206            updateBinaryExpression,
207            createConditionalExpression,
208            updateConditionalExpression,
209            createTemplateExpression,
210            updateTemplateExpression,
211            createTemplateHead,
212            createTemplateMiddle,
213            createTemplateTail,
214            createNoSubstitutionTemplateLiteral,
215            createTemplateLiteralLikeNode,
216            createYieldExpression,
217            updateYieldExpression,
218            createSpreadElement,
219            updateSpreadElement,
220            createClassExpression,
221            updateClassExpression,
222            createOmittedExpression,
223            createExpressionWithTypeArguments,
224            updateExpressionWithTypeArguments,
225            createAsExpression,
226            updateAsExpression,
227            createNonNullExpression,
228            updateNonNullExpression,
229            createSatisfiesExpression,
230            updateSatisfiesExpression,
231            createNonNullChain,
232            updateNonNullChain,
233            createMetaProperty,
234            updateMetaProperty,
235            createTemplateSpan,
236            updateTemplateSpan,
237            createSemicolonClassElement,
238            createBlock,
239            updateBlock,
240            createVariableStatement,
241            updateVariableStatement,
242            createEmptyStatement,
243            createExpressionStatement,
244            updateExpressionStatement,
245            createIfStatement,
246            updateIfStatement,
247            createDoStatement,
248            updateDoStatement,
249            createWhileStatement,
250            updateWhileStatement,
251            createForStatement,
252            updateForStatement,
253            createForInStatement,
254            updateForInStatement,
255            createForOfStatement,
256            updateForOfStatement,
257            createContinueStatement,
258            updateContinueStatement,
259            createBreakStatement,
260            updateBreakStatement,
261            createReturnStatement,
262            updateReturnStatement,
263            createWithStatement,
264            updateWithStatement,
265            createSwitchStatement,
266            updateSwitchStatement,
267            createLabeledStatement,
268            updateLabeledStatement,
269            createThrowStatement,
270            updateThrowStatement,
271            createTryStatement,
272            updateTryStatement,
273            createDebuggerStatement,
274            createVariableDeclaration,
275            updateVariableDeclaration,
276            createVariableDeclarationList,
277            updateVariableDeclarationList,
278            createFunctionDeclaration,
279            updateFunctionDeclaration,
280            createClassDeclaration,
281            updateClassDeclaration,
282            createStructDeclaration,
283            updateStructDeclaration,
284            createInterfaceDeclaration,
285            updateInterfaceDeclaration,
286            createTypeAliasDeclaration,
287            updateTypeAliasDeclaration,
288            createEnumDeclaration,
289            updateEnumDeclaration,
290            createModuleDeclaration,
291            updateModuleDeclaration,
292            createModuleBlock,
293            updateModuleBlock,
294            createCaseBlock,
295            updateCaseBlock,
296            createNamespaceExportDeclaration,
297            updateNamespaceExportDeclaration,
298            createImportEqualsDeclaration,
299            updateImportEqualsDeclaration,
300            createImportDeclaration,
301            updateImportDeclaration,
302            createImportClause,
303            updateImportClause,
304            createAssertClause,
305            updateAssertClause,
306            createAssertEntry,
307            updateAssertEntry,
308            createImportTypeAssertionContainer,
309            updateImportTypeAssertionContainer,
310            createNamespaceImport,
311            updateNamespaceImport,
312            createNamespaceExport,
313            updateNamespaceExport,
314            createNamedImports,
315            updateNamedImports,
316            createImportSpecifier,
317            updateImportSpecifier,
318            createExportAssignment,
319            updateExportAssignment,
320            createExportDeclaration,
321            updateExportDeclaration,
322            createNamedExports,
323            updateNamedExports,
324            createExportSpecifier,
325            updateExportSpecifier,
326            createMissingDeclaration,
327            createExternalModuleReference,
328            updateExternalModuleReference,
329            // lazily load factory members for JSDoc types with similar structure
330            get createJSDocAllType() { return getJSDocPrimaryTypeCreateFunction<JSDocAllType>(SyntaxKind.JSDocAllType); },
331            get createJSDocUnknownType() { return getJSDocPrimaryTypeCreateFunction<JSDocUnknownType>(SyntaxKind.JSDocUnknownType); },
332            get createJSDocNonNullableType() { return getJSDocPrePostfixUnaryTypeCreateFunction<JSDocNonNullableType>(SyntaxKind.JSDocNonNullableType); },
333            get updateJSDocNonNullableType() { return getJSDocPrePostfixUnaryTypeUpdateFunction<JSDocNonNullableType>(SyntaxKind.JSDocNonNullableType); },
334            get createJSDocNullableType() { return getJSDocPrePostfixUnaryTypeCreateFunction<JSDocNullableType>(SyntaxKind.JSDocNullableType); },
335            get updateJSDocNullableType() { return getJSDocPrePostfixUnaryTypeUpdateFunction<JSDocNullableType>(SyntaxKind.JSDocNullableType); },
336            get createJSDocOptionalType() { return getJSDocUnaryTypeCreateFunction<JSDocOptionalType>(SyntaxKind.JSDocOptionalType); },
337            get updateJSDocOptionalType() { return getJSDocUnaryTypeUpdateFunction<JSDocOptionalType>(SyntaxKind.JSDocOptionalType); },
338            get createJSDocVariadicType() { return getJSDocUnaryTypeCreateFunction<JSDocVariadicType>(SyntaxKind.JSDocVariadicType); },
339            get updateJSDocVariadicType() { return getJSDocUnaryTypeUpdateFunction<JSDocVariadicType>(SyntaxKind.JSDocVariadicType); },
340            get createJSDocNamepathType() { return getJSDocUnaryTypeCreateFunction<JSDocNamepathType>(SyntaxKind.JSDocNamepathType); },
341            get updateJSDocNamepathType() { return getJSDocUnaryTypeUpdateFunction<JSDocNamepathType>(SyntaxKind.JSDocNamepathType); },
342            createJSDocFunctionType,
343            updateJSDocFunctionType,
344            createJSDocTypeLiteral,
345            updateJSDocTypeLiteral,
346            createJSDocTypeExpression,
347            updateJSDocTypeExpression,
348            createJSDocSignature,
349            updateJSDocSignature,
350            createJSDocTemplateTag,
351            updateJSDocTemplateTag,
352            createJSDocTypedefTag,
353            updateJSDocTypedefTag,
354            createJSDocParameterTag,
355            updateJSDocParameterTag,
356            createJSDocPropertyTag,
357            updateJSDocPropertyTag,
358            createJSDocCallbackTag,
359            updateJSDocCallbackTag,
360            createJSDocAugmentsTag,
361            updateJSDocAugmentsTag,
362            createJSDocImplementsTag,
363            updateJSDocImplementsTag,
364            createJSDocSeeTag,
365            updateJSDocSeeTag,
366            createJSDocNameReference,
367            updateJSDocNameReference,
368            createJSDocMemberName,
369            updateJSDocMemberName,
370            createJSDocLink,
371            updateJSDocLink,
372            createJSDocLinkCode,
373            updateJSDocLinkCode,
374            createJSDocLinkPlain,
375            updateJSDocLinkPlain,
376            // lazily load factory members for JSDoc tags with similar structure
377            get createJSDocTypeTag() { return getJSDocTypeLikeTagCreateFunction<JSDocTypeTag>(SyntaxKind.JSDocTypeTag); },
378            get updateJSDocTypeTag() { return getJSDocTypeLikeTagUpdateFunction<JSDocTypeTag>(SyntaxKind.JSDocTypeTag); },
379            get createJSDocReturnTag() { return getJSDocTypeLikeTagCreateFunction<JSDocReturnTag>(SyntaxKind.JSDocReturnTag); },
380            get updateJSDocReturnTag() { return getJSDocTypeLikeTagUpdateFunction<JSDocReturnTag>(SyntaxKind.JSDocReturnTag); },
381            get createJSDocThisTag() { return getJSDocTypeLikeTagCreateFunction<JSDocThisTag>(SyntaxKind.JSDocThisTag); },
382            get updateJSDocThisTag() { return getJSDocTypeLikeTagUpdateFunction<JSDocThisTag>(SyntaxKind.JSDocThisTag); },
383            get createJSDocEnumTag() { return getJSDocTypeLikeTagCreateFunction<JSDocEnumTag>(SyntaxKind.JSDocEnumTag); },
384            get updateJSDocEnumTag() { return getJSDocTypeLikeTagUpdateFunction<JSDocEnumTag>(SyntaxKind.JSDocEnumTag); },
385            get createJSDocAuthorTag() { return getJSDocSimpleTagCreateFunction<JSDocAuthorTag>(SyntaxKind.JSDocAuthorTag); },
386            get updateJSDocAuthorTag() { return getJSDocSimpleTagUpdateFunction<JSDocAuthorTag>(SyntaxKind.JSDocAuthorTag); },
387            get createJSDocClassTag() { return getJSDocSimpleTagCreateFunction<JSDocClassTag>(SyntaxKind.JSDocClassTag); },
388            get updateJSDocClassTag() { return getJSDocSimpleTagUpdateFunction<JSDocClassTag>(SyntaxKind.JSDocClassTag); },
389            get createJSDocPublicTag() { return getJSDocSimpleTagCreateFunction<JSDocPublicTag>(SyntaxKind.JSDocPublicTag); },
390            get updateJSDocPublicTag() { return getJSDocSimpleTagUpdateFunction<JSDocPublicTag>(SyntaxKind.JSDocPublicTag); },
391            get createJSDocPrivateTag() { return getJSDocSimpleTagCreateFunction<JSDocPrivateTag>(SyntaxKind.JSDocPrivateTag); },
392            get updateJSDocPrivateTag() { return getJSDocSimpleTagUpdateFunction<JSDocPrivateTag>(SyntaxKind.JSDocPrivateTag); },
393            get createJSDocProtectedTag() { return getJSDocSimpleTagCreateFunction<JSDocProtectedTag>(SyntaxKind.JSDocProtectedTag); },
394            get updateJSDocProtectedTag() { return getJSDocSimpleTagUpdateFunction<JSDocProtectedTag>(SyntaxKind.JSDocProtectedTag); },
395            get createJSDocReadonlyTag() { return getJSDocSimpleTagCreateFunction<JSDocReadonlyTag>(SyntaxKind.JSDocReadonlyTag); },
396            get updateJSDocReadonlyTag() { return getJSDocSimpleTagUpdateFunction<JSDocReadonlyTag>(SyntaxKind.JSDocReadonlyTag); },
397            get createJSDocOverrideTag() { return getJSDocSimpleTagCreateFunction<JSDocOverrideTag>(SyntaxKind.JSDocOverrideTag); },
398            get updateJSDocOverrideTag() { return getJSDocSimpleTagUpdateFunction<JSDocOverrideTag>(SyntaxKind.JSDocOverrideTag); },
399            get createJSDocDeprecatedTag() { return getJSDocSimpleTagCreateFunction<JSDocDeprecatedTag>(SyntaxKind.JSDocDeprecatedTag); },
400            get updateJSDocDeprecatedTag() { return getJSDocSimpleTagUpdateFunction<JSDocDeprecatedTag>(SyntaxKind.JSDocDeprecatedTag); },
401            createJSDocUnknownTag,
402            updateJSDocUnknownTag,
403            createJSDocText,
404            updateJSDocText,
405            createJSDocComment,
406            updateJSDocComment,
407            createJsxElement,
408            updateJsxElement,
409            createJsxSelfClosingElement,
410            updateJsxSelfClosingElement,
411            createJsxOpeningElement,
412            updateJsxOpeningElement,
413            createJsxClosingElement,
414            updateJsxClosingElement,
415            createJsxFragment,
416            createJsxText,
417            updateJsxText,
418            createJsxOpeningFragment,
419            createJsxJsxClosingFragment,
420            updateJsxFragment,
421            createJsxAttribute,
422            updateJsxAttribute,
423            createJsxAttributes,
424            updateJsxAttributes,
425            createJsxSpreadAttribute,
426            updateJsxSpreadAttribute,
427            createJsxExpression,
428            updateJsxExpression,
429            createCaseClause,
430            updateCaseClause,
431            createDefaultClause,
432            updateDefaultClause,
433            createHeritageClause,
434            updateHeritageClause,
435            createCatchClause,
436            updateCatchClause,
437            createPropertyAssignment,
438            updatePropertyAssignment,
439            createShorthandPropertyAssignment,
440            updateShorthandPropertyAssignment,
441            createSpreadAssignment,
442            updateSpreadAssignment,
443            createEnumMember,
444            updateEnumMember,
445            createSourceFile,
446            updateSourceFile,
447            createBundle,
448            updateBundle,
449            createUnparsedSource,
450            createUnparsedPrologue,
451            createUnparsedPrepend,
452            createUnparsedTextLike,
453            createUnparsedSyntheticReference,
454            createInputFiles,
455            createSyntheticExpression,
456            createSyntaxList,
457            createNotEmittedStatement,
458            createPartiallyEmittedExpression,
459            updatePartiallyEmittedExpression,
460            createCommaListExpression,
461            updateCommaListExpression,
462            createEndOfDeclarationMarker,
463            createMergeDeclarationMarker,
464            createSyntheticReferenceExpression,
465            updateSyntheticReferenceExpression,
466            cloneNode,
467
468            // Lazily load factory methods for common operator factories and utilities
469            get createComma() { return getBinaryCreateFunction(SyntaxKind.CommaToken); },
470            get createAssignment() { return getBinaryCreateFunction(SyntaxKind.EqualsToken) as NodeFactory["createAssignment"]; },
471            get createLogicalOr() { return getBinaryCreateFunction(SyntaxKind.BarBarToken); },
472            get createLogicalAnd() { return getBinaryCreateFunction(SyntaxKind.AmpersandAmpersandToken); },
473            get createBitwiseOr() { return getBinaryCreateFunction(SyntaxKind.BarToken); },
474            get createBitwiseXor() { return getBinaryCreateFunction(SyntaxKind.CaretToken); },
475            get createBitwiseAnd() { return getBinaryCreateFunction(SyntaxKind.AmpersandToken); },
476            get createStrictEquality() { return getBinaryCreateFunction(SyntaxKind.EqualsEqualsEqualsToken); },
477            get createStrictInequality() { return getBinaryCreateFunction(SyntaxKind.ExclamationEqualsEqualsToken); },
478            get createEquality() { return getBinaryCreateFunction(SyntaxKind.EqualsEqualsToken); },
479            get createInequality() { return getBinaryCreateFunction(SyntaxKind.ExclamationEqualsToken); },
480            get createLessThan() { return getBinaryCreateFunction(SyntaxKind.LessThanToken); },
481            get createLessThanEquals() { return getBinaryCreateFunction(SyntaxKind.LessThanEqualsToken); },
482            get createGreaterThan() { return getBinaryCreateFunction(SyntaxKind.GreaterThanToken); },
483            get createGreaterThanEquals() { return getBinaryCreateFunction(SyntaxKind.GreaterThanEqualsToken); },
484            get createLeftShift() { return getBinaryCreateFunction(SyntaxKind.LessThanLessThanToken); },
485            get createRightShift() { return getBinaryCreateFunction(SyntaxKind.GreaterThanGreaterThanToken); },
486            get createUnsignedRightShift() { return getBinaryCreateFunction(SyntaxKind.GreaterThanGreaterThanGreaterThanToken); },
487            get createAdd() { return getBinaryCreateFunction(SyntaxKind.PlusToken); },
488            get createSubtract() { return getBinaryCreateFunction(SyntaxKind.MinusToken); },
489            get createMultiply() { return getBinaryCreateFunction(SyntaxKind.AsteriskToken); },
490            get createDivide() { return getBinaryCreateFunction(SyntaxKind.SlashToken); },
491            get createModulo() { return getBinaryCreateFunction(SyntaxKind.PercentToken); },
492            get createExponent() { return getBinaryCreateFunction(SyntaxKind.AsteriskAsteriskToken); },
493            get createPrefixPlus() { return getPrefixUnaryCreateFunction(SyntaxKind.PlusToken); },
494            get createPrefixMinus() { return getPrefixUnaryCreateFunction(SyntaxKind.MinusToken); },
495            get createPrefixIncrement() { return getPrefixUnaryCreateFunction(SyntaxKind.PlusPlusToken); },
496            get createPrefixDecrement() { return getPrefixUnaryCreateFunction(SyntaxKind.MinusMinusToken); },
497            get createBitwiseNot() { return getPrefixUnaryCreateFunction(SyntaxKind.TildeToken); },
498            get createLogicalNot() { return getPrefixUnaryCreateFunction(SyntaxKind.ExclamationToken); },
499            get createPostfixIncrement() { return getPostfixUnaryCreateFunction(SyntaxKind.PlusPlusToken); },
500            get createPostfixDecrement() { return getPostfixUnaryCreateFunction(SyntaxKind.MinusMinusToken); },
501
502            // Compound nodes
503            createImmediatelyInvokedFunctionExpression,
504            createImmediatelyInvokedArrowFunction,
505            createVoidZero,
506            createExportDefault,
507            createExternalModuleExport,
508            createTypeCheck,
509            createMethodCall,
510            createGlobalMethodCall,
511            createFunctionBindCall,
512            createFunctionCallCall,
513            createFunctionApplyCall,
514            createArraySliceCall,
515            createArrayConcatCall,
516            createObjectDefinePropertyCall,
517            createReflectGetCall,
518            createReflectSetCall,
519            createPropertyDescriptor,
520            createCallBinding,
521            createAssignmentTargetWrapper,
522
523            // Utilities
524            inlineExpressions,
525            getInternalName,
526            getLocalName,
527            getExportName,
528            getDeclarationName,
529            getNamespaceMemberName,
530            getExternalModuleOrNamespaceExportName,
531            restoreOuterExpressions,
532            restoreEnclosingLabel,
533            createUseStrictPrologue,
534            copyPrologue,
535            copyStandardPrologue,
536            copyCustomPrologue,
537            ensureUseStrict,
538            liftToBlock,
539            mergeLexicalEnvironment,
540            updateModifiers,
541        };
542
543        return factory;
544
545        // @api
546        function createNodeArray<T extends Node>(elements?: readonly T[], hasTrailingComma?: boolean): NodeArray<T> {
547            if (elements === undefined || elements === emptyArray) {
548                elements = [];
549            }
550            else if (isNodeArray(elements)) {
551                if (hasTrailingComma === undefined || elements.hasTrailingComma === hasTrailingComma) {
552                    // Ensure the transform flags have been aggregated for this NodeArray
553                    if (elements.transformFlags === undefined) {
554                        aggregateChildrenFlags(elements as MutableNodeArray<T>);
555                    }
556                    Debug.attachNodeArrayDebugInfo(elements);
557                    return elements;
558                }
559
560                // This *was* a `NodeArray`, but the `hasTrailingComma` option differs. Recreate the
561                // array with the same elements, text range, and transform flags but with the updated
562                // value for `hasTrailingComma`
563                const array = elements.slice() as MutableNodeArray<T>;
564                array.pos = elements.pos;
565                array.end = elements.end;
566                array.hasTrailingComma = hasTrailingComma;
567                array.transformFlags = elements.transformFlags;
568                Debug.attachNodeArrayDebugInfo(array);
569                return array;
570            }
571
572            // Since the element list of a node array is typically created by starting with an empty array and
573            // repeatedly calling push(), the list may not have the optimal memory layout. We invoke slice() for
574            // small arrays (1 to 4 elements) to give the VM a chance to allocate an optimal representation.
575            const length = elements.length;
576            const array = (length >= 1 && length <= 4 ? elements.slice() : elements) as MutableNodeArray<T>;
577            setTextRangePosEnd(array, -1, -1);
578            array.hasTrailingComma = !!hasTrailingComma;
579            aggregateChildrenFlags(array);
580            Debug.attachNodeArrayDebugInfo(array);
581            return array;
582        }
583
584        function createBaseNode<T extends Node>(kind: T["kind"]) {
585            return baseFactory.createBaseNode(kind) as Mutable<T>;
586        }
587
588        function createBaseDeclaration<T extends Declaration | VariableStatement | ImportDeclaration>(
589            kind: T["kind"],
590        ) {
591            const node = createBaseNode(kind);
592            // NOTE: The following properties are commonly set by the binder and are added here to
593            // ensure declarations have a stable shape.
594            node.symbol = undefined!; // initialized by binder
595            node.localSymbol = undefined; // initialized by binder
596            node.locals = undefined; // initialized by binder
597            node.nextContainer = undefined; // initialized by binder
598            return node;
599        }
600
601        function createBaseNamedDeclaration<T extends NamedDeclaration>(
602            kind: T["kind"],
603            modifiers: readonly ModifierLike[] | undefined,
604            name: Identifier | PrivateIdentifier | StringLiteralLike | NumericLiteral | ComputedPropertyName | BindingPattern | string | undefined
605        ) {
606            const node = createBaseDeclaration(kind);
607            name = asName(name);
608            node.name = name;
609            if (canHaveModifiers(node)) {
610                (node as Mutable<HasModifiers>).modifiers = asNodeArray(modifiers);
611                (node as Mutable<HasModifiers>).transformFlags |= propagateChildrenFlags(node.modifiers);
612                // node.decorators = filter(node.modifiers, isDecorator);
613            }
614
615            // The PropertyName of a member is allowed to be `await`.
616            // We don't need to exclude `await` for type signatures since types
617            // don't propagate child flags.
618            if (name) {
619                switch (node.kind) {
620                    case SyntaxKind.MethodDeclaration:
621                    case SyntaxKind.GetAccessor:
622                    case SyntaxKind.SetAccessor:
623                    case SyntaxKind.PropertyDeclaration:
624                    case SyntaxKind.PropertyAssignment:
625                        if (isIdentifier(name)) {
626                            node.transformFlags |= propagateIdentifierNameFlags(name);
627                            break;
628                        }
629                        // fall through
630                    default:
631                        node.transformFlags |= propagateChildFlags(name);
632                        break;
633                }
634            }
635            return node;
636        }
637
638        function createBaseGenericNamedDeclaration<T extends NamedDeclaration & { typeParameters?: NodeArray<TypeParameterDeclaration> }>(
639            kind: T["kind"],
640            modifiers: readonly ModifierLike[] | undefined,
641            name: Identifier | PrivateIdentifier | StringLiteralLike | NumericLiteral | ComputedPropertyName | BindingPattern | string | undefined,
642            typeParameters: readonly TypeParameterDeclaration[] | undefined
643        ) {
644            const node = createBaseNamedDeclaration(
645                kind,
646                modifiers,
647                name
648            );
649            node.typeParameters = asNodeArray(typeParameters);
650            node.transformFlags |= propagateChildrenFlags(node.typeParameters);
651            if (typeParameters) node.transformFlags |= TransformFlags.ContainsTypeScript;
652            return node;
653        }
654
655        function createBaseSignatureDeclaration<T extends SignatureDeclarationBase>(
656            kind: T["kind"],
657            modifiers: readonly ModifierLike[] | undefined,
658            name: Identifier | PrivateIdentifier | StringLiteralLike | NumericLiteral | ComputedPropertyName | BindingPattern | string | undefined,
659            typeParameters: readonly TypeParameterDeclaration[] | undefined,
660            parameters: readonly ParameterDeclaration[] | undefined,
661            type: TypeNode | undefined
662        ) {
663            const node = createBaseGenericNamedDeclaration(
664                kind,
665                modifiers,
666                name,
667                typeParameters
668            );
669            node.parameters = createNodeArray(parameters);
670            node.type = type;
671            node.transformFlags |=
672                propagateChildrenFlags(node.parameters) |
673                propagateChildFlags(node.type);
674            if (type) node.transformFlags |= TransformFlags.ContainsTypeScript;
675
676            // The following properties are used for quick info
677            node.typeArguments = undefined;
678            return node;
679        }
680
681        function finishUpdateBaseSignatureDeclaration<T extends SignatureDeclarationBase>(updated: Mutable<T>, original: T) {
682            if (updated !== original) {
683                // copy children used for quick info
684                updated.typeArguments = original.typeArguments;
685            }
686            return update(updated, original);
687        }
688
689        function createBaseFunctionLikeDeclaration<T extends FunctionLikeDeclaration>(
690            kind: T["kind"],
691            modifiers: readonly ModifierLike[] | undefined,
692            name: Identifier | PrivateIdentifier | StringLiteralLike | NumericLiteral | ComputedPropertyName | BindingPattern | string | undefined,
693            typeParameters: readonly TypeParameterDeclaration[] | undefined,
694            parameters: readonly ParameterDeclaration[] | undefined,
695            type: TypeNode | undefined,
696            body: T["body"]
697        ) {
698            const node = createBaseSignatureDeclaration(
699                kind,
700                modifiers,
701                name,
702                typeParameters,
703                parameters,
704                type
705            );
706            node.body = body;
707            node.transformFlags |= propagateChildFlags(node.body) & ~TransformFlags.ContainsPossibleTopLevelAwait;
708            if (!body) node.transformFlags |= TransformFlags.ContainsTypeScript;
709            return node;
710        }
711
712        function createBaseInterfaceOrClassLikeDeclaration<T extends InterfaceDeclaration | ClassLikeDeclaration>(
713            kind: T["kind"],
714            modifiers: readonly ModifierLike[] | undefined,
715            name: string | Identifier | undefined,
716            typeParameters: readonly TypeParameterDeclaration[] | undefined,
717            heritageClauses: readonly HeritageClause[] | undefined
718        ) {
719            const node = createBaseGenericNamedDeclaration(
720                kind,
721                modifiers,
722                name,
723                typeParameters
724            );
725            node.heritageClauses = asNodeArray(heritageClauses);
726            node.transformFlags |= propagateChildrenFlags(node.heritageClauses);
727            return node;
728        }
729
730        function createBaseClassLikeDeclaration<T extends ClassLikeDeclaration>(
731            kind: T["kind"],
732            modifiers: readonly ModifierLike[] | undefined,
733            name: string | Identifier | undefined,
734            typeParameters: readonly TypeParameterDeclaration[] | undefined,
735            heritageClauses: readonly HeritageClause[] | undefined,
736            members: readonly ClassElement[]
737        ) {
738            const node = createBaseInterfaceOrClassLikeDeclaration(
739                kind,
740                modifiers,
741                name,
742                typeParameters,
743                heritageClauses
744            );
745            node.members = createNodeArray(members);
746            node.transformFlags |= propagateChildrenFlags(node.members);
747            return node;
748        }
749
750        function createBaseBindingLikeDeclaration<T extends PropertyDeclaration | VariableDeclaration | ParameterDeclaration | BindingElement>(
751            kind: T["kind"],
752            modifiers: readonly ModifierLike[] | undefined,
753            name: string | T["name"] | undefined,
754            initializer: Expression | undefined
755        ) {
756            const node = createBaseNamedDeclaration(
757                kind,
758                modifiers,
759                name
760            );
761            node.initializer = initializer;
762            node.transformFlags |= propagateChildFlags(node.initializer);
763            return node;
764        }
765
766        function createBaseVariableLikeDeclaration<T extends PropertyDeclaration | VariableDeclaration | ParameterDeclaration>(
767            kind: T["kind"],
768            modifiers: readonly ModifierLike[] | undefined,
769            name: string | T["name"] | undefined,
770            type: TypeNode | undefined,
771            initializer: Expression | undefined
772        ) {
773            const node = createBaseBindingLikeDeclaration(
774                kind,
775                modifiers,
776                name,
777                initializer
778            );
779            node.type = type;
780            node.transformFlags |= propagateChildFlags(type);
781            if (type) node.transformFlags |= TransformFlags.ContainsTypeScript;
782            return node;
783        }
784
785        //
786        // Literals
787        //
788
789        function createBaseLiteral<T extends LiteralToken>(
790            kind: T["kind"],
791            text: string
792        ) {
793            const node = createBaseToken(kind);
794            node.text = text;
795            return node;
796        }
797
798        // @api
799        function createNumericLiteral(value: string | number, numericLiteralFlags: TokenFlags = TokenFlags.None): NumericLiteral {
800            const node = createBaseLiteral<NumericLiteral>(SyntaxKind.NumericLiteral, typeof value === "number" ? value + "" : value);
801            node.numericLiteralFlags = numericLiteralFlags;
802            if (numericLiteralFlags & TokenFlags.BinaryOrOctalSpecifier) node.transformFlags |= TransformFlags.ContainsES2015;
803            return node;
804        }
805
806        // @api
807        function createBigIntLiteral(value: string | PseudoBigInt): BigIntLiteral {
808            const node = createBaseLiteral<BigIntLiteral>(SyntaxKind.BigIntLiteral, typeof value === "string" ? value : pseudoBigIntToString(value) + "n");
809            node.transformFlags |= TransformFlags.ContainsESNext;
810            return node;
811        }
812
813        function createBaseStringLiteral(text: string, isSingleQuote?: boolean) {
814            const node = createBaseLiteral<StringLiteral>(SyntaxKind.StringLiteral, text);
815            node.singleQuote = isSingleQuote;
816            return node;
817        }
818
819        // @api
820        function createStringLiteral(text: string, isSingleQuote?: boolean, hasExtendedUnicodeEscape?: boolean): StringLiteral {
821            const node = createBaseStringLiteral(text, isSingleQuote);
822            node.hasExtendedUnicodeEscape = hasExtendedUnicodeEscape;
823            if (hasExtendedUnicodeEscape) node.transformFlags |= TransformFlags.ContainsES2015;
824            return node;
825        }
826
827        // @api
828        function createStringLiteralFromNode(sourceNode: PropertyNameLiteral | PrivateIdentifier): StringLiteral {
829            const node = createBaseStringLiteral(getTextOfIdentifierOrLiteral(sourceNode), /*isSingleQuote*/ undefined);
830            node.textSourceNode = sourceNode;
831            return node;
832        }
833
834        // @api
835        function createRegularExpressionLiteral(text: string): RegularExpressionLiteral {
836            const node = createBaseLiteral<RegularExpressionLiteral>(SyntaxKind.RegularExpressionLiteral, text);
837            return node;
838        }
839
840        // @api
841        function createLiteralLikeNode(kind: LiteralToken["kind"] | SyntaxKind.JsxTextAllWhiteSpaces, text: string): LiteralToken {
842            switch (kind) {
843                case SyntaxKind.NumericLiteral: return createNumericLiteral(text, /*numericLiteralFlags*/ 0);
844                case SyntaxKind.BigIntLiteral: return createBigIntLiteral(text);
845                case SyntaxKind.StringLiteral: return createStringLiteral(text, /*isSingleQuote*/ undefined);
846                case SyntaxKind.JsxText: return createJsxText(text, /*containsOnlyTriviaWhiteSpaces*/ false);
847                case SyntaxKind.JsxTextAllWhiteSpaces: return createJsxText(text, /*containsOnlyTriviaWhiteSpaces*/ true);
848                case SyntaxKind.RegularExpressionLiteral: return createRegularExpressionLiteral(text);
849                case SyntaxKind.NoSubstitutionTemplateLiteral: return createTemplateLiteralLikeNode(kind, text, /*rawText*/ undefined, /*templateFlags*/ 0) as NoSubstitutionTemplateLiteral;
850            }
851        }
852
853        //
854        // Identifiers
855        //
856
857        function createBaseIdentifier(text: string, originalKeywordKind: SyntaxKind | undefined) {
858            if (originalKeywordKind === undefined && text) {
859                originalKeywordKind = stringToToken(text);
860            }
861            if (originalKeywordKind === SyntaxKind.Identifier) {
862                originalKeywordKind = undefined;
863            }
864            const node = baseFactory.createBaseIdentifierNode(SyntaxKind.Identifier) as Mutable<Identifier>;
865            node.originalKeywordKind = originalKeywordKind;
866            node.escapedText = escapeLeadingUnderscores(text);
867            return node;
868        }
869
870        function createBaseGeneratedIdentifier(text: string, autoGenerateFlags: GeneratedIdentifierFlags, prefix: string | GeneratedNamePart | undefined, suffix: string | undefined) {
871            const node = createBaseIdentifier(text, /*originalKeywordKind*/ undefined) as Mutable<GeneratedIdentifier>;
872            node.autoGenerateFlags = autoGenerateFlags;
873            node.autoGenerateId = nextAutoGenerateId;
874            node.autoGeneratePrefix = prefix;
875            node.autoGenerateSuffix = suffix;
876            nextAutoGenerateId++;
877            return node;
878        }
879
880        // @api
881        function createIdentifier(text: string, typeArguments?: readonly (TypeNode | TypeParameterDeclaration)[], originalKeywordKind?: SyntaxKind, hasExtendedUnicodeEscape?: boolean): Identifier {
882            const node = createBaseIdentifier(text, originalKeywordKind);
883            if (typeArguments) {
884                // NOTE: we do not use `setChildren` here because typeArguments in an identifier do not contribute to transformations
885                node.typeArguments = createNodeArray(typeArguments);
886            }
887            if (node.originalKeywordKind === SyntaxKind.AwaitKeyword) {
888                node.transformFlags |= TransformFlags.ContainsPossibleTopLevelAwait;
889            }
890            if (hasExtendedUnicodeEscape) {
891                node.hasExtendedUnicodeEscape = hasExtendedUnicodeEscape;
892                node.transformFlags |= TransformFlags.ContainsES2015;
893            }
894            return node;
895        }
896
897        // @api
898        function updateIdentifier(node: Identifier, typeArguments?: NodeArray<TypeNode | TypeParameterDeclaration> | undefined): Identifier {
899            return node.typeArguments !== typeArguments
900                ? update(createIdentifier(idText(node), typeArguments), node)
901                : node;
902        }
903
904        // @api
905        function createTempVariable(recordTempVariable: ((node: Identifier) => void) | undefined, reservedInNestedScopes?: boolean, prefix?: string | GeneratedNamePart, suffix?: string): GeneratedIdentifier {
906            let flags = GeneratedIdentifierFlags.Auto;
907            if (reservedInNestedScopes) flags |= GeneratedIdentifierFlags.ReservedInNestedScopes;
908            const name = createBaseGeneratedIdentifier("", flags, prefix, suffix);
909            if (recordTempVariable) {
910                recordTempVariable(name);
911            }
912            return name;
913        }
914
915        /** Create a unique temporary variable for use in a loop. */
916        // @api
917        function createLoopVariable(reservedInNestedScopes?: boolean): Identifier {
918            let flags = GeneratedIdentifierFlags.Loop;
919            if (reservedInNestedScopes) flags |= GeneratedIdentifierFlags.ReservedInNestedScopes;
920            return createBaseGeneratedIdentifier("", flags, /*prefix*/ undefined, /*suffix*/ undefined);
921        }
922
923        /** Create a unique name based on the supplied text. */
924        // @api
925        function createUniqueName(text: string, flags: GeneratedIdentifierFlags = GeneratedIdentifierFlags.None, prefix?: string | GeneratedNamePart, suffix?: string): Identifier {
926            Debug.assert(!(flags & GeneratedIdentifierFlags.KindMask), "Argument out of range: flags");
927            Debug.assert((flags & (GeneratedIdentifierFlags.Optimistic | GeneratedIdentifierFlags.FileLevel)) !== GeneratedIdentifierFlags.FileLevel, "GeneratedIdentifierFlags.FileLevel cannot be set without also setting GeneratedIdentifierFlags.Optimistic");
928            return createBaseGeneratedIdentifier(text, GeneratedIdentifierFlags.Unique | flags, prefix, suffix);
929        }
930
931        /** Create a unique name generated for a node. */
932        // @api
933        function getGeneratedNameForNode(node: Node | undefined, flags: GeneratedIdentifierFlags = 0, prefix?: string | GeneratedNamePart, suffix?: string): Identifier {
934            Debug.assert(!(flags & GeneratedIdentifierFlags.KindMask), "Argument out of range: flags");
935            const text = !node ? "" :
936                isMemberName(node) ? formatGeneratedName(/*privateName*/ false, prefix, node, suffix, idText) :
937                `generated@${getNodeId(node)}`;
938            if (prefix || suffix) flags |= GeneratedIdentifierFlags.Optimistic;
939            const name = createBaseGeneratedIdentifier(text, GeneratedIdentifierFlags.Node | flags, prefix, suffix);
940            name.original = node;
941            return name;
942        }
943
944        function createBasePrivateIdentifier(text: string) {
945            const node = baseFactory.createBasePrivateIdentifierNode(SyntaxKind.PrivateIdentifier) as Mutable<PrivateIdentifier>;
946            node.escapedText = escapeLeadingUnderscores(text);
947            node.transformFlags |= TransformFlags.ContainsClassFields;
948            return node;
949        }
950
951        // @api
952        function createPrivateIdentifier(text: string): PrivateIdentifier {
953            if (!startsWith(text, "#")) Debug.fail("First character of private identifier must be #: " + text);
954            return createBasePrivateIdentifier(text);
955        }
956
957        function createBaseGeneratedPrivateIdentifier(text: string, autoGenerateFlags: GeneratedIdentifierFlags, prefix: string | GeneratedNamePart | undefined, suffix: string | undefined) {
958            const node = createBasePrivateIdentifier(text);
959            node.autoGenerateFlags = autoGenerateFlags;
960            node.autoGenerateId = nextAutoGenerateId;
961            node.autoGeneratePrefix = prefix;
962            node.autoGenerateSuffix = suffix;
963            nextAutoGenerateId++;
964            return node;
965        }
966
967        /** Create a unique name based on the supplied text. */
968        // @api
969        function createUniquePrivateName(text?: string, prefix?: string | GeneratedNamePart, suffix?: string): PrivateIdentifier {
970            if (text && !startsWith(text, "#")) Debug.fail("First character of private identifier must be #: " + text);
971            const autoGenerateFlags = GeneratedIdentifierFlags.ReservedInNestedScopes |
972                (text ? GeneratedIdentifierFlags.Unique : GeneratedIdentifierFlags.Auto);
973            return createBaseGeneratedPrivateIdentifier(text ?? "", autoGenerateFlags, prefix, suffix);
974        }
975
976        // @api
977        function getGeneratedPrivateNameForNode(node: Node, prefix?: string | GeneratedNamePart, suffix?: string): PrivateIdentifier {
978            const text = isMemberName(node) ? formatGeneratedName(/*privateName*/ true, prefix, node, suffix, idText) :
979                `#generated@${getNodeId(node)}`;
980            const flags = prefix || suffix ? GeneratedIdentifierFlags.Optimistic : GeneratedIdentifierFlags.None;
981            const name = createBaseGeneratedPrivateIdentifier(text, GeneratedIdentifierFlags.Node | flags, prefix, suffix);
982            name.original = node;
983            return name;
984        }
985
986        //
987        // Punctuation
988        //
989
990        function createBaseToken<T extends Node>(kind: T["kind"]) {
991            return baseFactory.createBaseTokenNode(kind) as Mutable<T>;
992        }
993
994        // @api
995        function createToken(token: SyntaxKind.SuperKeyword): SuperExpression;
996        function createToken(token: SyntaxKind.ThisKeyword): ThisExpression;
997        function createToken(token: SyntaxKind.NullKeyword): NullLiteral;
998        function createToken(token: SyntaxKind.TrueKeyword): TrueLiteral;
999        function createToken(token: SyntaxKind.FalseKeyword): FalseLiteral;
1000        function createToken<TKind extends PunctuationSyntaxKind>(token: TKind): PunctuationToken<TKind>;
1001        function createToken<TKind extends KeywordTypeSyntaxKind>(token: TKind): KeywordTypeNode<TKind>;
1002        function createToken<TKind extends ModifierSyntaxKind>(token: TKind): ModifierToken<TKind>;
1003        function createToken<TKind extends KeywordSyntaxKind>(token: TKind): KeywordToken<TKind>;
1004        function createToken<TKind extends SyntaxKind.Unknown | SyntaxKind.EndOfFileToken>(token: TKind): Token<TKind>;
1005        function createToken<TKind extends SyntaxKind>(token: TKind): Token<TKind>;
1006        function createToken<TKind extends SyntaxKind>(token: TKind) {
1007            Debug.assert(token >= SyntaxKind.FirstToken && token <= SyntaxKind.LastToken, "Invalid token");
1008            Debug.assert(token <= SyntaxKind.FirstTemplateToken || token >= SyntaxKind.LastTemplateToken, "Invalid token. Use 'createTemplateLiteralLikeNode' to create template literals.");
1009            Debug.assert(token <= SyntaxKind.FirstLiteralToken || token >= SyntaxKind.LastLiteralToken, "Invalid token. Use 'createLiteralLikeNode' to create literals.");
1010            Debug.assert(token !== SyntaxKind.Identifier, "Invalid token. Use 'createIdentifier' to create identifiers");
1011            const node = createBaseToken<Token<TKind>>(token);
1012            let transformFlags = TransformFlags.None;
1013            switch (token) {
1014                case SyntaxKind.AsyncKeyword:
1015                    // 'async' modifier is ES2017 (async functions) or ES2018 (async generators)
1016                    transformFlags =
1017                        TransformFlags.ContainsES2017 |
1018                        TransformFlags.ContainsES2018;
1019                    break;
1020
1021                case SyntaxKind.PublicKeyword:
1022                case SyntaxKind.PrivateKeyword:
1023                case SyntaxKind.ProtectedKeyword:
1024                case SyntaxKind.ReadonlyKeyword:
1025                case SyntaxKind.AbstractKeyword:
1026                case SyntaxKind.DeclareKeyword:
1027                case SyntaxKind.ConstKeyword:
1028                case SyntaxKind.AnyKeyword:
1029                case SyntaxKind.NumberKeyword:
1030                case SyntaxKind.BigIntKeyword:
1031                case SyntaxKind.NeverKeyword:
1032                case SyntaxKind.ObjectKeyword:
1033                case SyntaxKind.InKeyword:
1034                case SyntaxKind.OutKeyword:
1035                case SyntaxKind.OverrideKeyword:
1036                case SyntaxKind.StringKeyword:
1037                case SyntaxKind.BooleanKeyword:
1038                case SyntaxKind.SymbolKeyword:
1039                case SyntaxKind.VoidKeyword:
1040                case SyntaxKind.UnknownKeyword:
1041                case SyntaxKind.UndefinedKeyword: // `undefined` is an Identifier in the expression case.
1042                    transformFlags = TransformFlags.ContainsTypeScript;
1043                    break;
1044                case SyntaxKind.SuperKeyword:
1045                    transformFlags = TransformFlags.ContainsES2015 | TransformFlags.ContainsLexicalSuper;
1046                    break;
1047                case SyntaxKind.StaticKeyword:
1048                    transformFlags = TransformFlags.ContainsES2015;
1049                    break;
1050                case SyntaxKind.AccessorKeyword:
1051                    transformFlags = TransformFlags.ContainsClassFields;
1052                    break;
1053                case SyntaxKind.ThisKeyword:
1054                    // 'this' indicates a lexical 'this'
1055                    transformFlags = TransformFlags.ContainsLexicalThis;
1056                    break;
1057            }
1058            if (transformFlags) {
1059                node.transformFlags |= transformFlags;
1060            }
1061            return node;
1062        }
1063
1064        //
1065        // Reserved words
1066        //
1067
1068        // @api
1069        function createSuper() {
1070            return createToken(SyntaxKind.SuperKeyword);
1071        }
1072
1073        // @api
1074        function createThis() {
1075            return createToken(SyntaxKind.ThisKeyword);
1076        }
1077
1078        // @api
1079        function createNull() {
1080            return createToken(SyntaxKind.NullKeyword);
1081        }
1082
1083        // @api
1084        function createTrue() {
1085            return createToken(SyntaxKind.TrueKeyword);
1086        }
1087
1088        // @api
1089        function createFalse() {
1090            return createToken(SyntaxKind.FalseKeyword);
1091        }
1092
1093        //
1094        // Modifiers
1095        //
1096
1097        // @api
1098        function createModifier<T extends ModifierSyntaxKind>(kind: T) {
1099            return createToken(kind);
1100        }
1101
1102        // @api
1103        function createModifiersFromModifierFlags(flags: ModifierFlags) {
1104            const result: Modifier[] = [];
1105            if (flags & ModifierFlags.Export) result.push(createModifier(SyntaxKind.ExportKeyword));
1106            if (flags & ModifierFlags.Ambient) result.push(createModifier(SyntaxKind.DeclareKeyword));
1107            if (flags & ModifierFlags.Default) result.push(createModifier(SyntaxKind.DefaultKeyword));
1108            if (flags & ModifierFlags.Const) result.push(createModifier(SyntaxKind.ConstKeyword));
1109            if (flags & ModifierFlags.Public) result.push(createModifier(SyntaxKind.PublicKeyword));
1110            if (flags & ModifierFlags.Private) result.push(createModifier(SyntaxKind.PrivateKeyword));
1111            if (flags & ModifierFlags.Protected) result.push(createModifier(SyntaxKind.ProtectedKeyword));
1112            if (flags & ModifierFlags.Abstract) result.push(createModifier(SyntaxKind.AbstractKeyword));
1113            if (flags & ModifierFlags.Static) result.push(createModifier(SyntaxKind.StaticKeyword));
1114            if (flags & ModifierFlags.Override) result.push(createModifier(SyntaxKind.OverrideKeyword));
1115            if (flags & ModifierFlags.Readonly) result.push(createModifier(SyntaxKind.ReadonlyKeyword));
1116            if (flags & ModifierFlags.Accessor) result.push(createModifier(SyntaxKind.AccessorKeyword));
1117            if (flags & ModifierFlags.Async) result.push(createModifier(SyntaxKind.AsyncKeyword));
1118            if (flags & ModifierFlags.In) result.push(createModifier(SyntaxKind.InKeyword));
1119            if (flags & ModifierFlags.Out) result.push(createModifier(SyntaxKind.OutKeyword));
1120            return result.length ? result : undefined;
1121        }
1122
1123        //
1124        // Names
1125        //
1126
1127        // @api
1128        function createQualifiedName(left: EntityName, right: string | Identifier) {
1129            const node = createBaseNode<QualifiedName>(SyntaxKind.QualifiedName);
1130            node.left = left;
1131            node.right = asName(right);
1132            node.transformFlags |=
1133                propagateChildFlags(node.left) |
1134                propagateIdentifierNameFlags(node.right);
1135            return node;
1136        }
1137
1138        // @api
1139        function updateQualifiedName(node: QualifiedName, left: EntityName, right: Identifier) {
1140            return node.left !== left
1141                || node.right !== right
1142                ? update(createQualifiedName(left, right), node)
1143                : node;
1144        }
1145
1146        // @api
1147        function createComputedPropertyName(expression: Expression) {
1148            const node = createBaseNode<ComputedPropertyName>(SyntaxKind.ComputedPropertyName);
1149            node.expression = parenthesizerRules().parenthesizeExpressionOfComputedPropertyName(expression);
1150            node.transformFlags |=
1151                propagateChildFlags(node.expression) |
1152                TransformFlags.ContainsES2015 |
1153                TransformFlags.ContainsComputedPropertyName;
1154            return node;
1155        }
1156
1157        // @api
1158        function updateComputedPropertyName(node: ComputedPropertyName, expression: Expression) {
1159            return node.expression !== expression
1160                ? update(createComputedPropertyName(expression), node)
1161                : node;
1162        }
1163
1164        //
1165        // Signature elements
1166        //
1167
1168        // @api
1169        function createTypeParameterDeclaration(modifiers: readonly Modifier[] | undefined, name: string | Identifier, constraint?: TypeNode, defaultType?: TypeNode): TypeParameterDeclaration {
1170            const node = createBaseNamedDeclaration<TypeParameterDeclaration>(
1171                SyntaxKind.TypeParameter,
1172                modifiers,
1173                name
1174            );
1175            node.constraint = constraint;
1176            node.default = defaultType;
1177            node.transformFlags = TransformFlags.ContainsTypeScript;
1178            return node;
1179        }
1180
1181        // @api
1182        function updateTypeParameterDeclaration(node: TypeParameterDeclaration, modifiers: readonly Modifier[] | undefined, name: Identifier, constraint: TypeNode | undefined, defaultType: TypeNode | undefined): TypeParameterDeclaration {
1183            return node.modifiers !== modifiers
1184                || node.name !== name
1185                || node.constraint !== constraint
1186                || node.default !== defaultType
1187                ? update(createTypeParameterDeclaration(modifiers, name, constraint, defaultType), node)
1188                : node;
1189        }
1190
1191        // @api
1192        function createParameterDeclaration(
1193            modifiers: readonly ModifierLike[] | undefined,
1194            dotDotDotToken: DotDotDotToken | undefined,
1195            name: string | BindingName,
1196            questionToken?: QuestionToken,
1197            type?: TypeNode,
1198            initializer?: Expression
1199        ) {
1200            const node = createBaseVariableLikeDeclaration<ParameterDeclaration>(
1201                SyntaxKind.Parameter,
1202                modifiers,
1203                name,
1204                type,
1205                initializer && parenthesizerRules().parenthesizeExpressionForDisallowedComma(initializer)
1206            );
1207            node.dotDotDotToken = dotDotDotToken;
1208            node.questionToken = questionToken;
1209            if (isThisIdentifier(node.name)) {
1210                node.transformFlags = TransformFlags.ContainsTypeScript;
1211            }
1212            else {
1213                node.transformFlags |=
1214                    propagateChildFlags(node.dotDotDotToken) |
1215                    propagateChildFlags(node.questionToken);
1216                if (questionToken) node.transformFlags |= TransformFlags.ContainsTypeScript;
1217                if (modifiersToFlags(node.modifiers) & ModifierFlags.ParameterPropertyModifier) node.transformFlags |= TransformFlags.ContainsTypeScriptClassSyntax;
1218                if (initializer || dotDotDotToken) node.transformFlags |= TransformFlags.ContainsES2015;
1219            }
1220            return node;
1221        }
1222
1223        // @api
1224        function updateParameterDeclaration(
1225            node: ParameterDeclaration,
1226            modifiers: readonly ModifierLike[] | undefined,
1227            dotDotDotToken: DotDotDotToken | undefined,
1228            name: string | BindingName,
1229            questionToken: QuestionToken | undefined,
1230            type: TypeNode | undefined,
1231            initializer: Expression | undefined
1232        ) {
1233            return node.modifiers !== modifiers
1234                || node.dotDotDotToken !== dotDotDotToken
1235                || node.name !== name
1236                || node.questionToken !== questionToken
1237                || node.type !== type
1238                || node.initializer !== initializer
1239                ? update(createParameterDeclaration(modifiers, dotDotDotToken, name, questionToken, type, initializer), node)
1240                : node;
1241        }
1242
1243        // @api
1244        function createDecorator(expression: Expression) {
1245            const node = createBaseNode<Decorator>(SyntaxKind.Decorator);
1246            node.expression = parenthesizerRules().parenthesizeLeftSideOfAccess(expression, /*optionalChain*/ false);
1247            node.transformFlags |=
1248                propagateChildFlags(node.expression) |
1249                TransformFlags.ContainsTypeScript |
1250                TransformFlags.ContainsTypeScriptClassSyntax |
1251                TransformFlags.ContainsDecorators;
1252            return node;
1253        }
1254
1255        // @api
1256        function updateDecorator(node: Decorator, expression: Expression) {
1257            return node.expression !== expression
1258                ? update(createDecorator(expression), node)
1259                : node;
1260        }
1261
1262        //
1263        // Type Elements
1264        //
1265
1266        // @api
1267        function createPropertySignature(
1268            modifiers: readonly ModifierLike[] | undefined,
1269            name: PropertyName | string,
1270            questionToken: QuestionToken | undefined,
1271            type: TypeNode | undefined
1272        ): PropertySignature {
1273            const node = createBaseNamedDeclaration<PropertySignature>(
1274                SyntaxKind.PropertySignature,
1275                modifiers,
1276                name
1277            );
1278            node.type = type;
1279            node.questionToken = questionToken;
1280            node.transformFlags = TransformFlags.ContainsTypeScript;
1281
1282            // The following properties are used only to report grammar errors
1283            node.initializer = undefined;
1284            return node;
1285        }
1286
1287        // @api
1288        function updatePropertySignature(
1289            node: PropertySignature,
1290            modifiers: readonly ModifierLike[] | undefined,
1291            name: PropertyName,
1292            questionToken: QuestionToken | undefined,
1293            type: TypeNode | undefined
1294        ) {
1295            return node.modifiers !== modifiers
1296                || node.name !== name
1297                || node.questionToken !== questionToken
1298                || node.type !== type
1299                ? finishUpdatePropertySignature(createPropertySignature(modifiers, name, questionToken, type), node)
1300                : node;
1301        }
1302
1303        function finishUpdatePropertySignature(updated: Mutable<PropertySignature>, original: PropertySignature) {
1304            if (updated !== original) {
1305                // copy children used only for error reporting
1306                updated.initializer = original.initializer;
1307            }
1308            return update(updated, original);
1309        }
1310
1311        // @api
1312        function createPropertyDeclaration(
1313            modifiers: readonly ModifierLike[] | undefined,
1314            name: string | PropertyName,
1315            questionOrExclamationToken: QuestionToken | ExclamationToken | undefined,
1316            type: TypeNode | undefined,
1317            initializer: Expression | undefined
1318        ) {
1319            const node = createBaseVariableLikeDeclaration<PropertyDeclaration>(
1320                SyntaxKind.PropertyDeclaration,
1321                modifiers,
1322                name,
1323                type,
1324                initializer
1325            );
1326            node.questionToken = questionOrExclamationToken && isQuestionToken(questionOrExclamationToken) ? questionOrExclamationToken : undefined;
1327            node.exclamationToken = questionOrExclamationToken && isExclamationToken(questionOrExclamationToken) ? questionOrExclamationToken : undefined;
1328            node.transformFlags |=
1329                propagateChildFlags(node.questionToken) |
1330                propagateChildFlags(node.exclamationToken) |
1331                TransformFlags.ContainsClassFields;
1332            if (isComputedPropertyName(node.name) || (hasStaticModifier(node) && node.initializer)) {
1333                node.transformFlags |= TransformFlags.ContainsTypeScriptClassSyntax;
1334            }
1335            if (questionOrExclamationToken || modifiersToFlags(node.modifiers) & ModifierFlags.Ambient) {
1336                node.transformFlags |= TransformFlags.ContainsTypeScript;
1337            }
1338            return node;
1339        }
1340
1341        // @api
1342        function updatePropertyDeclaration(
1343            node: PropertyDeclaration,
1344            modifiers: readonly ModifierLike[] | undefined,
1345            name: string | PropertyName,
1346            questionOrExclamationToken: QuestionToken | ExclamationToken | undefined,
1347            type: TypeNode | undefined,
1348            initializer: Expression | undefined
1349        ) {
1350            return node.modifiers !== modifiers
1351                || node.name !== name
1352                || node.questionToken !== (questionOrExclamationToken !== undefined && isQuestionToken(questionOrExclamationToken) ? questionOrExclamationToken : undefined)
1353                || node.exclamationToken !== (questionOrExclamationToken !== undefined && isExclamationToken(questionOrExclamationToken) ? questionOrExclamationToken : undefined)
1354                || node.type !== type
1355                || node.initializer !== initializer
1356                ? update(createPropertyDeclaration(modifiers, name, questionOrExclamationToken, type, initializer), node)
1357                : node;
1358        }
1359
1360        // @api
1361        function createMethodSignature(
1362            modifiers: readonly ModifierLike[] | undefined,
1363            name: string | PropertyName,
1364            questionToken: QuestionToken | undefined,
1365            typeParameters: readonly TypeParameterDeclaration[] | undefined,
1366            parameters: readonly ParameterDeclaration[],
1367            type: TypeNode | undefined
1368        ) {
1369            const node = createBaseSignatureDeclaration<MethodSignature>(
1370                SyntaxKind.MethodSignature,
1371                modifiers,
1372                name,
1373                typeParameters,
1374                parameters,
1375                type
1376            );
1377            node.questionToken = questionToken;
1378            node.transformFlags = TransformFlags.ContainsTypeScript;
1379            return node;
1380        }
1381
1382        // @api
1383        function updateMethodSignature(
1384            node: MethodSignature,
1385            modifiers: readonly ModifierLike[] | undefined,
1386            name: PropertyName,
1387            questionToken: QuestionToken | undefined,
1388            typeParameters: NodeArray<TypeParameterDeclaration> | undefined,
1389            parameters: NodeArray<ParameterDeclaration>,
1390            type: TypeNode | undefined
1391        ) {
1392            return node.modifiers !== modifiers
1393                || node.name !== name
1394                || node.questionToken !== questionToken
1395                || node.typeParameters !== typeParameters
1396                || node.parameters !== parameters
1397                || node.type !== type
1398                ? finishUpdateBaseSignatureDeclaration(createMethodSignature(modifiers, name, questionToken, typeParameters, parameters, type), node)
1399                : node;
1400        }
1401
1402        // @api
1403        function createMethodDeclaration(
1404            modifiers: readonly ModifierLike[] | undefined,
1405            asteriskToken: AsteriskToken | undefined,
1406            name: string | PropertyName,
1407            questionToken: QuestionToken | undefined,
1408            typeParameters: readonly TypeParameterDeclaration[] | undefined,
1409            parameters: readonly ParameterDeclaration[],
1410            type: TypeNode | undefined,
1411            body: Block | undefined
1412        ) {
1413            const node = createBaseFunctionLikeDeclaration<MethodDeclaration>(
1414                SyntaxKind.MethodDeclaration,
1415                modifiers,
1416                name,
1417                typeParameters,
1418                parameters,
1419                type,
1420                body
1421            );
1422            node.asteriskToken = asteriskToken;
1423            node.questionToken = questionToken;
1424            node.transformFlags |=
1425                propagateChildFlags(node.asteriskToken) |
1426                propagateChildFlags(node.questionToken) |
1427                TransformFlags.ContainsES2015;
1428            if (questionToken) {
1429                node.transformFlags |= TransformFlags.ContainsTypeScript;
1430            }
1431            if (modifiersToFlags(node.modifiers) & ModifierFlags.Async) {
1432                if (asteriskToken) {
1433                    node.transformFlags |= TransformFlags.ContainsES2018;
1434                }
1435                else {
1436                    node.transformFlags |= TransformFlags.ContainsES2017;
1437                }
1438            }
1439            else if (asteriskToken) {
1440                node.transformFlags |= TransformFlags.ContainsGenerator;
1441            }
1442
1443            // The following properties are used only to report grammar errors
1444            node.exclamationToken = undefined;
1445            return node;
1446        }
1447
1448        // @api
1449        function updateMethodDeclaration(
1450            node: MethodDeclaration,
1451            modifiers: readonly ModifierLike[] | undefined,
1452            asteriskToken: AsteriskToken | undefined,
1453            name: PropertyName,
1454            questionToken: QuestionToken | undefined,
1455            typeParameters: readonly TypeParameterDeclaration[] | undefined,
1456            parameters: readonly ParameterDeclaration[],
1457            type: TypeNode | undefined,
1458            body: Block | undefined
1459        ) {
1460            return node.modifiers !== modifiers
1461                || node.asteriskToken !== asteriskToken
1462                || node.name !== name
1463                || node.questionToken !== questionToken
1464                || node.typeParameters !== typeParameters
1465                || node.parameters !== parameters
1466                || node.type !== type
1467                || node.body !== body
1468                ? finishUpdateMethodDeclaration(createMethodDeclaration(modifiers, asteriskToken, name, questionToken, typeParameters, parameters, type, body), node)
1469                : node;
1470        }
1471
1472        function finishUpdateMethodDeclaration(updated: Mutable<MethodDeclaration>, original: MethodDeclaration) {
1473            if (updated !== original) {
1474                updated.exclamationToken = original.exclamationToken;
1475            }
1476            return update(updated, original);
1477        }
1478
1479        // @api
1480        function createClassStaticBlockDeclaration(
1481            body: Block
1482        ): ClassStaticBlockDeclaration {
1483            const node = createBaseGenericNamedDeclaration<ClassStaticBlockDeclaration>(
1484                SyntaxKind.ClassStaticBlockDeclaration,
1485                /*modifiers*/ undefined,
1486                /*name*/ undefined,
1487                /*typeParameters*/ undefined
1488            );
1489            node.body = body;
1490            node.transformFlags = propagateChildFlags(body) | TransformFlags.ContainsClassFields;
1491
1492            // The following properties are used only to report grammar errors
1493            node.illegalDecorators = undefined;
1494            node.modifiers = undefined;
1495            return node;
1496        }
1497
1498        // @api
1499        function updateClassStaticBlockDeclaration(
1500            node: ClassStaticBlockDeclaration,
1501            body: Block
1502        ): ClassStaticBlockDeclaration {
1503            return node.body !== body
1504                ? finishUpdateClassStaticBlockDeclaration(createClassStaticBlockDeclaration(body), node)
1505                : node;
1506        }
1507
1508        function finishUpdateClassStaticBlockDeclaration(updated: Mutable<ClassStaticBlockDeclaration>, original: ClassStaticBlockDeclaration) {
1509            if (updated !== original) {
1510                updated.illegalDecorators = original.illegalDecorators;
1511                updated.modifiers = original.modifiers;
1512            }
1513            return update(updated, original);
1514        }
1515
1516        // @api
1517        function createConstructorDeclaration(
1518            modifiers: readonly Modifier[] | undefined,
1519            parameters: readonly ParameterDeclaration[],
1520            body: Block | undefined
1521        ) {
1522            const node = createBaseFunctionLikeDeclaration<ConstructorDeclaration>(
1523                SyntaxKind.Constructor,
1524                modifiers,
1525                /*name*/ undefined,
1526                /*typeParameters*/ undefined,
1527                parameters,
1528                /*type*/ undefined,
1529                body
1530            );
1531            node.transformFlags |= TransformFlags.ContainsES2015;
1532
1533            // The following properties are used only to report grammar errors
1534            node.illegalDecorators = undefined;
1535            node.typeParameters = undefined;
1536            node.type = undefined;
1537            return node;
1538        }
1539
1540        // @api
1541        function updateConstructorDeclaration(
1542            node: ConstructorDeclaration,
1543            modifiers: readonly Modifier[] | undefined,
1544            parameters: readonly ParameterDeclaration[],
1545            body: Block | undefined
1546        ) {
1547            return node.modifiers !== modifiers
1548                || node.parameters !== parameters
1549                || node.body !== body
1550                ? finishUpdateConstructorDeclaration(createConstructorDeclaration(modifiers, parameters, body), node)
1551                : node;
1552        }
1553
1554        function finishUpdateConstructorDeclaration(updated: Mutable<ConstructorDeclaration>, original: ConstructorDeclaration) {
1555            if (updated !== original) {
1556                updated.illegalDecorators = original.illegalDecorators;
1557                updated.typeParameters = original.typeParameters;
1558                updated.type = original.type;
1559            }
1560            return finishUpdateBaseSignatureDeclaration(updated, original);
1561        }
1562
1563        // @api
1564        function createGetAccessorDeclaration(
1565            modifiers: readonly ModifierLike[] | undefined,
1566            name: string | PropertyName,
1567            parameters: readonly ParameterDeclaration[],
1568            type: TypeNode | undefined,
1569            body: Block | undefined
1570        ) {
1571            const node = createBaseFunctionLikeDeclaration<GetAccessorDeclaration>(
1572                SyntaxKind.GetAccessor,
1573                modifiers,
1574                name,
1575                /*typeParameters*/ undefined,
1576                parameters,
1577                type,
1578                body
1579            );
1580
1581            // The following properties are used only to report grammar errors
1582            node.typeParameters = undefined;
1583            return node;
1584        }
1585
1586        // @api
1587        function updateGetAccessorDeclaration(
1588            node: GetAccessorDeclaration,
1589            modifiers: readonly ModifierLike[] | undefined,
1590            name: PropertyName,
1591            parameters: readonly ParameterDeclaration[],
1592            type: TypeNode | undefined,
1593            body: Block | undefined
1594        ) {
1595            return node.modifiers !== modifiers
1596                || node.name !== name
1597                || node.parameters !== parameters
1598                || node.type !== type
1599                || node.body !== body
1600                ? finishUpdateGetAccessorDeclaration(createGetAccessorDeclaration(modifiers, name, parameters, type, body), node)
1601                : node;
1602        }
1603
1604        function finishUpdateGetAccessorDeclaration(updated: Mutable<GetAccessorDeclaration>, original: GetAccessorDeclaration) {
1605            if (updated !== original) {
1606                updated.typeParameters = original.typeParameters;
1607            }
1608            return finishUpdateBaseSignatureDeclaration(updated, original);
1609        }
1610
1611        // @api
1612        function createSetAccessorDeclaration(
1613            modifiers: readonly ModifierLike[] | undefined,
1614            name: string | PropertyName,
1615            parameters: readonly ParameterDeclaration[],
1616            body: Block | undefined
1617        ) {
1618            const node = createBaseFunctionLikeDeclaration<SetAccessorDeclaration>(
1619                SyntaxKind.SetAccessor,
1620                modifiers,
1621                name,
1622                /*typeParameters*/ undefined,
1623                parameters,
1624                /*type*/ undefined,
1625                body
1626            );
1627
1628            // The following properties are used only to report grammar errors
1629            node.typeParameters = undefined;
1630            node.type = undefined;
1631            return node;
1632        }
1633
1634        // @api
1635        function updateSetAccessorDeclaration(
1636            node: SetAccessorDeclaration,
1637            modifiers: readonly ModifierLike[] | undefined,
1638            name: PropertyName,
1639            parameters: readonly ParameterDeclaration[],
1640            body: Block | undefined
1641        ) {
1642            return node.modifiers !== modifiers
1643                || node.name !== name
1644                || node.parameters !== parameters
1645                || node.body !== body
1646                ? finishUpdateSetAccessorDeclaration(createSetAccessorDeclaration(modifiers, name, parameters, body), node)
1647                : node;
1648        }
1649
1650        function finishUpdateSetAccessorDeclaration(updated: Mutable<SetAccessorDeclaration>, original: SetAccessorDeclaration) {
1651            if (updated !== original) {
1652                updated.typeParameters = original.typeParameters;
1653                updated.type = original.type;
1654            }
1655            return finishUpdateBaseSignatureDeclaration(updated, original);
1656        }
1657
1658        // @api
1659        function createCallSignature(
1660            typeParameters: readonly TypeParameterDeclaration[] | undefined,
1661            parameters: readonly ParameterDeclaration[],
1662            type: TypeNode | undefined
1663        ): CallSignatureDeclaration {
1664            const node = createBaseSignatureDeclaration<CallSignatureDeclaration>(
1665                SyntaxKind.CallSignature,
1666                /*modifiers*/ undefined,
1667                /*name*/ undefined,
1668                typeParameters,
1669                parameters,
1670                type
1671            );
1672            node.transformFlags = TransformFlags.ContainsTypeScript;
1673            return node;
1674        }
1675
1676        // @api
1677        function updateCallSignature(
1678            node: CallSignatureDeclaration,
1679            typeParameters: NodeArray<TypeParameterDeclaration> | undefined,
1680            parameters: NodeArray<ParameterDeclaration>,
1681            type: TypeNode | undefined
1682        ) {
1683            return node.typeParameters !== typeParameters
1684                || node.parameters !== parameters
1685                || node.type !== type
1686                ? finishUpdateBaseSignatureDeclaration(createCallSignature(typeParameters, parameters, type), node)
1687                : node;
1688        }
1689
1690        // @api
1691        function createConstructSignature(
1692            typeParameters: readonly TypeParameterDeclaration[] | undefined,
1693            parameters: readonly ParameterDeclaration[],
1694            type: TypeNode | undefined
1695        ): ConstructSignatureDeclaration {
1696            const node = createBaseSignatureDeclaration<ConstructSignatureDeclaration>(
1697                SyntaxKind.ConstructSignature,
1698                /*modifiers*/ undefined,
1699                /*name*/ undefined,
1700                typeParameters,
1701                parameters,
1702                type
1703            );
1704            node.transformFlags = TransformFlags.ContainsTypeScript;
1705            return node;
1706        }
1707
1708        // @api
1709        function updateConstructSignature(
1710            node: ConstructSignatureDeclaration,
1711            typeParameters: NodeArray<TypeParameterDeclaration> | undefined,
1712            parameters: NodeArray<ParameterDeclaration>,
1713            type: TypeNode | undefined
1714        ) {
1715            return node.typeParameters !== typeParameters
1716                || node.parameters !== parameters
1717                || node.type !== type
1718                ? finishUpdateBaseSignatureDeclaration(createConstructSignature(typeParameters, parameters, type), node)
1719                : node;
1720        }
1721
1722        // @api
1723        function createIndexSignature(
1724            modifiers: readonly Modifier[] | undefined,
1725            parameters: readonly ParameterDeclaration[],
1726            type: TypeNode | undefined
1727        ): IndexSignatureDeclaration {
1728            const node = createBaseSignatureDeclaration<IndexSignatureDeclaration>(
1729                SyntaxKind.IndexSignature,
1730                modifiers,
1731                /*name*/ undefined,
1732                /*typeParameters*/ undefined,
1733                parameters,
1734                type
1735            );
1736            node.transformFlags = TransformFlags.ContainsTypeScript;
1737            return node;
1738        }
1739
1740        // @api
1741        function updateIndexSignature(
1742            node: IndexSignatureDeclaration,
1743            modifiers: readonly Modifier[] | undefined,
1744            parameters: readonly ParameterDeclaration[],
1745            type: TypeNode
1746        ) {
1747            return node.parameters !== parameters
1748                || node.type !== type
1749                || node.modifiers !== modifiers
1750                ? finishUpdateBaseSignatureDeclaration(createIndexSignature(modifiers, parameters, type), node)
1751                : node;
1752        }
1753
1754        // @api
1755        function createTemplateLiteralTypeSpan(type: TypeNode, literal: TemplateMiddle | TemplateTail) {
1756            const node = createBaseNode<TemplateLiteralTypeSpan>(SyntaxKind.TemplateLiteralTypeSpan);
1757            node.type = type;
1758            node.literal = literal;
1759            node.transformFlags = TransformFlags.ContainsTypeScript;
1760            return node;
1761        }
1762
1763        // @api
1764        function updateTemplateLiteralTypeSpan(node: TemplateLiteralTypeSpan, type: TypeNode, literal: TemplateMiddle | TemplateTail) {
1765            return node.type !== type
1766                || node.literal !== literal
1767                ? update(createTemplateLiteralTypeSpan(type, literal), node)
1768                : node;
1769        }
1770
1771        //
1772        // Types
1773        //
1774
1775        // @api
1776        function createKeywordTypeNode<TKind extends KeywordTypeSyntaxKind>(kind: TKind) {
1777            return createToken(kind);
1778        }
1779
1780        // @api
1781        function createTypePredicateNode(assertsModifier: AssertsKeyword | undefined, parameterName: Identifier | ThisTypeNode | string, type: TypeNode | undefined) {
1782            const node = createBaseNode<TypePredicateNode>(SyntaxKind.TypePredicate);
1783            node.assertsModifier = assertsModifier;
1784            node.parameterName = asName(parameterName);
1785            node.type = type;
1786            node.transformFlags = TransformFlags.ContainsTypeScript;
1787            return node;
1788        }
1789
1790        // @api
1791        function updateTypePredicateNode(node: TypePredicateNode, assertsModifier: AssertsKeyword | undefined, parameterName: Identifier | ThisTypeNode, type: TypeNode | undefined) {
1792            return node.assertsModifier !== assertsModifier
1793                || node.parameterName !== parameterName
1794                || node.type !== type
1795                ? update(createTypePredicateNode(assertsModifier, parameterName, type), node)
1796                : node;
1797        }
1798
1799        // @api
1800        function createTypeReferenceNode(typeName: string | EntityName, typeArguments: readonly TypeNode[] | undefined) {
1801            const node = createBaseNode<TypeReferenceNode>(SyntaxKind.TypeReference);
1802            node.typeName = asName(typeName);
1803            node.typeArguments = typeArguments && parenthesizerRules().parenthesizeTypeArguments(createNodeArray(typeArguments));
1804            node.transformFlags = TransformFlags.ContainsTypeScript;
1805            return node;
1806        }
1807
1808        // @api
1809        function updateTypeReferenceNode(node: TypeReferenceNode, typeName: EntityName, typeArguments: NodeArray<TypeNode> | undefined) {
1810            return node.typeName !== typeName
1811                || node.typeArguments !== typeArguments
1812                ? update(createTypeReferenceNode(typeName, typeArguments), node)
1813                : node;
1814        }
1815
1816        // @api
1817        function createFunctionTypeNode(
1818            typeParameters: readonly TypeParameterDeclaration[] | undefined,
1819            parameters: readonly ParameterDeclaration[],
1820            type: TypeNode | undefined
1821        ): FunctionTypeNode {
1822            const node = createBaseSignatureDeclaration<FunctionTypeNode>(
1823                SyntaxKind.FunctionType,
1824                /*modifiers*/ undefined,
1825                /*name*/ undefined,
1826                typeParameters,
1827                parameters,
1828                type
1829            );
1830            node.transformFlags = TransformFlags.ContainsTypeScript;
1831
1832            // The following properties are used only to report grammar errors
1833            node.modifiers = undefined;
1834            return node;
1835        }
1836
1837        // @api
1838        function updateFunctionTypeNode(
1839            node: FunctionTypeNode,
1840            typeParameters: NodeArray<TypeParameterDeclaration> | undefined,
1841            parameters: NodeArray<ParameterDeclaration>,
1842            type: TypeNode | undefined
1843        ) {
1844            return node.typeParameters !== typeParameters
1845                || node.parameters !== parameters
1846                || node.type !== type
1847                ? finishUpdateFunctionTypeNode(createFunctionTypeNode(typeParameters, parameters, type), node)
1848                : node;
1849        }
1850
1851        function finishUpdateFunctionTypeNode(updated: Mutable<FunctionTypeNode>, original: FunctionTypeNode) {
1852            if (updated !== original) {
1853                updated.modifiers = original.modifiers;
1854            }
1855            return finishUpdateBaseSignatureDeclaration(updated, original);
1856        }
1857
1858        // @api
1859        function createConstructorTypeNode(...args: Parameters<typeof createConstructorTypeNode1 | typeof createConstructorTypeNode2>) {
1860            return args.length === 4 ? createConstructorTypeNode1(...args) :
1861                args.length === 3 ? createConstructorTypeNode2(...args) :
1862                Debug.fail("Incorrect number of arguments specified.");
1863        }
1864
1865        function createConstructorTypeNode1(
1866            modifiers: readonly Modifier[] | undefined,
1867            typeParameters: readonly TypeParameterDeclaration[] | undefined,
1868            parameters: readonly ParameterDeclaration[],
1869            type: TypeNode | undefined
1870        ): ConstructorTypeNode {
1871            const node = createBaseSignatureDeclaration<ConstructorTypeNode>(
1872                SyntaxKind.ConstructorType,
1873                modifiers,
1874                /*name*/ undefined,
1875                typeParameters,
1876                parameters,
1877                type
1878            );
1879            node.transformFlags = TransformFlags.ContainsTypeScript;
1880            return node;
1881        }
1882
1883        /** @deprecated */
1884        function createConstructorTypeNode2(
1885            typeParameters: readonly TypeParameterDeclaration[] | undefined,
1886            parameters: readonly ParameterDeclaration[],
1887            type: TypeNode | undefined
1888        ): ConstructorTypeNode {
1889            return createConstructorTypeNode1(/*modifiers*/ undefined, typeParameters, parameters, type);
1890        }
1891
1892        // @api
1893        function updateConstructorTypeNode(...args: Parameters<typeof updateConstructorTypeNode1 | typeof updateConstructorTypeNode2>) {
1894            return args.length === 5 ? updateConstructorTypeNode1(...args) :
1895                args.length === 4 ? updateConstructorTypeNode2(...args) :
1896                Debug.fail("Incorrect number of arguments specified.");
1897        }
1898
1899        function updateConstructorTypeNode1(
1900            node: ConstructorTypeNode,
1901            modifiers: readonly Modifier[] | undefined,
1902            typeParameters: NodeArray<TypeParameterDeclaration> | undefined,
1903            parameters: NodeArray<ParameterDeclaration>,
1904            type: TypeNode | undefined
1905        ) {
1906            return node.modifiers !== modifiers
1907                || node.typeParameters !== typeParameters
1908                || node.parameters !== parameters
1909                || node.type !== type
1910                ? finishUpdateBaseSignatureDeclaration(createConstructorTypeNode(modifiers, typeParameters, parameters, type), node)
1911                : node;
1912        }
1913
1914        /** @deprecated */
1915        function updateConstructorTypeNode2(
1916            node: ConstructorTypeNode,
1917            typeParameters: NodeArray<TypeParameterDeclaration> | undefined,
1918            parameters: NodeArray<ParameterDeclaration>,
1919            type: TypeNode | undefined
1920        ) {
1921            return updateConstructorTypeNode1(node, node.modifiers, typeParameters, parameters, type);
1922        }
1923
1924        // @api
1925        function createTypeQueryNode(exprName: EntityName, typeArguments?: readonly TypeNode[]) {
1926            const node = createBaseNode<TypeQueryNode>(SyntaxKind.TypeQuery);
1927            node.exprName = exprName;
1928            node.typeArguments = typeArguments && parenthesizerRules().parenthesizeTypeArguments(typeArguments);
1929            node.transformFlags = TransformFlags.ContainsTypeScript;
1930            return node;
1931        }
1932
1933        // @api
1934        function updateTypeQueryNode(node: TypeQueryNode, exprName: EntityName, typeArguments?: readonly TypeNode[]) {
1935            return node.exprName !== exprName
1936                || node.typeArguments !== typeArguments
1937                ? update(createTypeQueryNode(exprName, typeArguments), node)
1938                : node;
1939        }
1940
1941        // @api
1942        function createTypeLiteralNode(members: readonly TypeElement[] | undefined) {
1943            const node = createBaseNode<TypeLiteralNode>(SyntaxKind.TypeLiteral);
1944            node.members = createNodeArray(members);
1945            node.transformFlags = TransformFlags.ContainsTypeScript;
1946            return node;
1947        }
1948
1949        // @api
1950        function updateTypeLiteralNode(node: TypeLiteralNode, members: NodeArray<TypeElement>) {
1951            return node.members !== members
1952                ? update(createTypeLiteralNode(members), node)
1953                : node;
1954        }
1955
1956        // @api
1957        function createArrayTypeNode(elementType: TypeNode) {
1958            const node = createBaseNode<ArrayTypeNode>(SyntaxKind.ArrayType);
1959            node.elementType = parenthesizerRules().parenthesizeNonArrayTypeOfPostfixType(elementType);
1960            node.transformFlags = TransformFlags.ContainsTypeScript;
1961            return node;
1962        }
1963
1964        // @api
1965        function updateArrayTypeNode(node: ArrayTypeNode, elementType: TypeNode): ArrayTypeNode {
1966            return node.elementType !== elementType
1967                ? update(createArrayTypeNode(elementType), node)
1968                : node;
1969        }
1970
1971        // @api
1972        function createTupleTypeNode(elements: readonly (TypeNode | NamedTupleMember)[]) {
1973            const node = createBaseNode<TupleTypeNode>(SyntaxKind.TupleType);
1974            node.elements = createNodeArray(parenthesizerRules().parenthesizeElementTypesOfTupleType(elements));
1975            node.transformFlags = TransformFlags.ContainsTypeScript;
1976            return node;
1977        }
1978
1979        // @api
1980        function updateTupleTypeNode(node: TupleTypeNode, elements: readonly (TypeNode | NamedTupleMember)[]) {
1981            return node.elements !== elements
1982                ? update(createTupleTypeNode(elements), node)
1983                : node;
1984        }
1985
1986        // @api
1987        function createNamedTupleMember(dotDotDotToken: DotDotDotToken | undefined, name: Identifier, questionToken: QuestionToken | undefined, type: TypeNode) {
1988            const node = createBaseNode<NamedTupleMember>(SyntaxKind.NamedTupleMember);
1989            node.dotDotDotToken = dotDotDotToken;
1990            node.name = name;
1991            node.questionToken = questionToken;
1992            node.type = type;
1993            node.transformFlags = TransformFlags.ContainsTypeScript;
1994            return node;
1995        }
1996
1997        // @api
1998        function updateNamedTupleMember(node: NamedTupleMember, dotDotDotToken: DotDotDotToken | undefined, name: Identifier, questionToken: QuestionToken | undefined, type: TypeNode) {
1999            return node.dotDotDotToken !== dotDotDotToken
2000                || node.name !== name
2001                || node.questionToken !== questionToken
2002                || node.type !== type
2003                ? update(createNamedTupleMember(dotDotDotToken, name, questionToken, type), node)
2004                : node;
2005        }
2006
2007        // @api
2008        function createOptionalTypeNode(type: TypeNode) {
2009            const node = createBaseNode<OptionalTypeNode>(SyntaxKind.OptionalType);
2010            node.type = parenthesizerRules().parenthesizeTypeOfOptionalType(type);
2011            node.transformFlags = TransformFlags.ContainsTypeScript;
2012            return node;
2013        }
2014
2015        // @api
2016        function updateOptionalTypeNode(node: OptionalTypeNode, type: TypeNode): OptionalTypeNode {
2017            return node.type !== type
2018                ? update(createOptionalTypeNode(type), node)
2019                : node;
2020        }
2021
2022        // @api
2023        function createRestTypeNode(type: TypeNode) {
2024            const node = createBaseNode<RestTypeNode>(SyntaxKind.RestType);
2025            node.type = type;
2026            node.transformFlags = TransformFlags.ContainsTypeScript;
2027            return node;
2028        }
2029
2030        // @api
2031        function updateRestTypeNode(node: RestTypeNode, type: TypeNode): RestTypeNode {
2032            return node.type !== type
2033                ? update(createRestTypeNode(type), node)
2034                : node;
2035        }
2036
2037        function createUnionOrIntersectionTypeNode(kind: SyntaxKind.UnionType | SyntaxKind.IntersectionType, types: readonly TypeNode[], parenthesize: (nodes: readonly TypeNode[]) => readonly TypeNode[]) {
2038            const node = createBaseNode<UnionTypeNode | IntersectionTypeNode>(kind);
2039            node.types = factory.createNodeArray(parenthesize(types));
2040            node.transformFlags = TransformFlags.ContainsTypeScript;
2041            return node;
2042        }
2043
2044        function updateUnionOrIntersectionTypeNode<T extends UnionOrIntersectionTypeNode>(node: T, types: NodeArray<TypeNode>, parenthesize: (nodes: readonly TypeNode[]) => readonly TypeNode[]): T {
2045            return node.types !== types
2046                ? update(createUnionOrIntersectionTypeNode(node.kind, types, parenthesize) as T, node)
2047                : node;
2048        }
2049
2050        // @api
2051        function createUnionTypeNode(types: readonly TypeNode[]): UnionTypeNode {
2052            return createUnionOrIntersectionTypeNode(SyntaxKind.UnionType, types, parenthesizerRules().parenthesizeConstituentTypesOfUnionType) as UnionTypeNode;
2053        }
2054
2055        // @api
2056        function updateUnionTypeNode(node: UnionTypeNode, types: NodeArray<TypeNode>) {
2057            return updateUnionOrIntersectionTypeNode(node, types, parenthesizerRules().parenthesizeConstituentTypesOfUnionType);
2058        }
2059
2060        // @api
2061        function createIntersectionTypeNode(types: readonly TypeNode[]): IntersectionTypeNode {
2062            return createUnionOrIntersectionTypeNode(SyntaxKind.IntersectionType, types, parenthesizerRules().parenthesizeConstituentTypesOfIntersectionType) as IntersectionTypeNode;
2063        }
2064
2065        // @api
2066        function updateIntersectionTypeNode(node: IntersectionTypeNode, types: NodeArray<TypeNode>) {
2067            return updateUnionOrIntersectionTypeNode(node, types, parenthesizerRules().parenthesizeConstituentTypesOfIntersectionType);
2068        }
2069
2070        // @api
2071        function createConditionalTypeNode(checkType: TypeNode, extendsType: TypeNode, trueType: TypeNode, falseType: TypeNode) {
2072            const node = createBaseNode<ConditionalTypeNode>(SyntaxKind.ConditionalType);
2073            node.checkType = parenthesizerRules().parenthesizeCheckTypeOfConditionalType(checkType);
2074            node.extendsType = parenthesizerRules().parenthesizeExtendsTypeOfConditionalType(extendsType);
2075            node.trueType = trueType;
2076            node.falseType = falseType;
2077            node.transformFlags = TransformFlags.ContainsTypeScript;
2078            return node;
2079        }
2080
2081        // @api
2082        function updateConditionalTypeNode(node: ConditionalTypeNode, checkType: TypeNode, extendsType: TypeNode, trueType: TypeNode, falseType: TypeNode) {
2083            return node.checkType !== checkType
2084                || node.extendsType !== extendsType
2085                || node.trueType !== trueType
2086                || node.falseType !== falseType
2087                ? update(createConditionalTypeNode(checkType, extendsType, trueType, falseType), node)
2088                : node;
2089        }
2090
2091        // @api
2092        function createInferTypeNode(typeParameter: TypeParameterDeclaration) {
2093            const node = createBaseNode<InferTypeNode>(SyntaxKind.InferType);
2094            node.typeParameter = typeParameter;
2095            node.transformFlags = TransformFlags.ContainsTypeScript;
2096            return node;
2097        }
2098
2099        // @api
2100        function updateInferTypeNode(node: InferTypeNode, typeParameter: TypeParameterDeclaration) {
2101            return node.typeParameter !== typeParameter
2102                ? update(createInferTypeNode(typeParameter), node)
2103                : node;
2104        }
2105
2106        // @api
2107        function createTemplateLiteralType(head: TemplateHead, templateSpans: readonly TemplateLiteralTypeSpan[]) {
2108            const node = createBaseNode<TemplateLiteralTypeNode>(SyntaxKind.TemplateLiteralType);
2109            node.head = head;
2110            node.templateSpans = createNodeArray(templateSpans);
2111            node.transformFlags = TransformFlags.ContainsTypeScript;
2112            return node;
2113        }
2114
2115        // @api
2116        function updateTemplateLiteralType(node: TemplateLiteralTypeNode, head: TemplateHead, templateSpans: readonly TemplateLiteralTypeSpan[]) {
2117            return node.head !== head
2118                || node.templateSpans !== templateSpans
2119                ? update(createTemplateLiteralType(head, templateSpans), node)
2120                : node;
2121        }
2122
2123        // @api
2124        function createImportTypeNode(
2125            argument: TypeNode,
2126            assertions?: ImportTypeAssertionContainer,
2127            qualifier?: EntityName,
2128            typeArguments?: readonly TypeNode[],
2129            isTypeOf = false
2130        ): ImportTypeNode {
2131            const node = createBaseNode<ImportTypeNode>(SyntaxKind.ImportType);
2132            node.argument = argument;
2133            node.assertions = assertions;
2134            node.qualifier = qualifier;
2135            node.typeArguments = typeArguments && parenthesizerRules().parenthesizeTypeArguments(typeArguments);
2136            node.isTypeOf = isTypeOf;
2137            node.transformFlags = TransformFlags.ContainsTypeScript;
2138            return node;
2139        }
2140
2141        // @api
2142        function updateImportTypeNode(
2143            node: ImportTypeNode,
2144            argument: TypeNode,
2145            assertions: ImportTypeAssertionContainer | undefined,
2146            qualifier: EntityName | undefined,
2147            typeArguments: readonly TypeNode[] | undefined,
2148            isTypeOf: boolean = node.isTypeOf
2149        ): ImportTypeNode {
2150            return node.argument !== argument
2151                || node.assertions !== assertions
2152                || node.qualifier !== qualifier
2153                || node.typeArguments !== typeArguments
2154                || node.isTypeOf !== isTypeOf
2155                ? update(createImportTypeNode(argument, assertions, qualifier, typeArguments, isTypeOf), node)
2156                : node;
2157        }
2158
2159        // @api
2160        function createParenthesizedType(type: TypeNode) {
2161            const node = createBaseNode<ParenthesizedTypeNode>(SyntaxKind.ParenthesizedType);
2162            node.type = type;
2163            node.transformFlags = TransformFlags.ContainsTypeScript;
2164            return node;
2165        }
2166
2167        // @api
2168        function updateParenthesizedType(node: ParenthesizedTypeNode, type: TypeNode) {
2169            return node.type !== type
2170                ? update(createParenthesizedType(type), node)
2171                : node;
2172        }
2173
2174        // @api
2175        function createThisTypeNode() {
2176            const node = createBaseNode<ThisTypeNode>(SyntaxKind.ThisType);
2177            node.transformFlags = TransformFlags.ContainsTypeScript;
2178            return node;
2179        }
2180
2181        // @api
2182        function createTypeOperatorNode(operator: SyntaxKind.KeyOfKeyword | SyntaxKind.UniqueKeyword | SyntaxKind.ReadonlyKeyword, type: TypeNode): TypeOperatorNode {
2183            const node = createBaseNode<TypeOperatorNode>(SyntaxKind.TypeOperator);
2184            node.operator = operator;
2185            node.type = operator === SyntaxKind.ReadonlyKeyword ?
2186                parenthesizerRules().parenthesizeOperandOfReadonlyTypeOperator(type) :
2187                parenthesizerRules().parenthesizeOperandOfTypeOperator(type);
2188            node.transformFlags = TransformFlags.ContainsTypeScript;
2189            return node;
2190        }
2191
2192        // @api
2193        function updateTypeOperatorNode(node: TypeOperatorNode, type: TypeNode) {
2194            return node.type !== type
2195                ? update(createTypeOperatorNode(node.operator, type), node)
2196                : node;
2197        }
2198
2199        // @api
2200        function createIndexedAccessTypeNode(objectType: TypeNode, indexType: TypeNode) {
2201            const node = createBaseNode<IndexedAccessTypeNode>(SyntaxKind.IndexedAccessType);
2202            node.objectType = parenthesizerRules().parenthesizeNonArrayTypeOfPostfixType(objectType);
2203            node.indexType = indexType;
2204            node.transformFlags = TransformFlags.ContainsTypeScript;
2205            return node;
2206        }
2207
2208        // @api
2209        function updateIndexedAccessTypeNode(node: IndexedAccessTypeNode, objectType: TypeNode, indexType: TypeNode) {
2210            return node.objectType !== objectType
2211                || node.indexType !== indexType
2212                ? update(createIndexedAccessTypeNode(objectType, indexType), node)
2213                : node;
2214        }
2215
2216        // @api
2217        function createMappedTypeNode(readonlyToken: ReadonlyKeyword | PlusToken | MinusToken | undefined, typeParameter: TypeParameterDeclaration, nameType: TypeNode | undefined, questionToken: QuestionToken | PlusToken | MinusToken | undefined, type: TypeNode | undefined, members: readonly TypeElement[] | undefined): MappedTypeNode {
2218            const node = createBaseNode<MappedTypeNode>(SyntaxKind.MappedType);
2219            node.readonlyToken = readonlyToken;
2220            node.typeParameter = typeParameter;
2221            node.nameType = nameType;
2222            node.questionToken = questionToken;
2223            node.type = type;
2224            node.members = members && createNodeArray(members);
2225            node.transformFlags = TransformFlags.ContainsTypeScript;
2226            return node;
2227        }
2228
2229        // @api
2230        function updateMappedTypeNode(node: MappedTypeNode, readonlyToken: ReadonlyKeyword | PlusToken | MinusToken | undefined, typeParameter: TypeParameterDeclaration, nameType: TypeNode | undefined, questionToken: QuestionToken | PlusToken | MinusToken | undefined, type: TypeNode | undefined, members: readonly TypeElement[] | undefined): MappedTypeNode {
2231            return node.readonlyToken !== readonlyToken
2232                || node.typeParameter !== typeParameter
2233                || node.nameType !== nameType
2234                || node.questionToken !== questionToken
2235                || node.type !== type
2236                || node.members !== members
2237                ? update(createMappedTypeNode(readonlyToken, typeParameter, nameType, questionToken, type, members), node)
2238                : node;
2239        }
2240
2241        // @api
2242        function createLiteralTypeNode(literal: LiteralTypeNode["literal"]) {
2243            const node = createBaseNode<LiteralTypeNode>(SyntaxKind.LiteralType);
2244            node.literal = literal;
2245            node.transformFlags = TransformFlags.ContainsTypeScript;
2246            return node;
2247        }
2248
2249        // @api
2250        function updateLiteralTypeNode(node: LiteralTypeNode, literal: LiteralTypeNode["literal"]) {
2251            return node.literal !== literal
2252                ? update(createLiteralTypeNode(literal), node)
2253                : node;
2254        }
2255
2256        //
2257        // Binding Patterns
2258        //
2259
2260        // @api
2261        function createObjectBindingPattern(elements: readonly BindingElement[]) {
2262            const node = createBaseNode<ObjectBindingPattern>(SyntaxKind.ObjectBindingPattern);
2263            node.elements = createNodeArray(elements);
2264            node.transformFlags |=
2265                propagateChildrenFlags(node.elements) |
2266                TransformFlags.ContainsES2015 |
2267                TransformFlags.ContainsBindingPattern;
2268            if (node.transformFlags & TransformFlags.ContainsRestOrSpread) {
2269                node.transformFlags |=
2270                    TransformFlags.ContainsES2018 |
2271                    TransformFlags.ContainsObjectRestOrSpread;
2272            }
2273            return node;
2274        }
2275
2276        // @api
2277        function updateObjectBindingPattern(node: ObjectBindingPattern, elements: readonly BindingElement[]) {
2278            return node.elements !== elements
2279                ? update(createObjectBindingPattern(elements), node)
2280                : node;
2281        }
2282
2283        // @api
2284        function createArrayBindingPattern(elements: readonly ArrayBindingElement[]) {
2285            const node = createBaseNode<ArrayBindingPattern>(SyntaxKind.ArrayBindingPattern);
2286            node.elements = createNodeArray(elements);
2287            node.transformFlags |=
2288                propagateChildrenFlags(node.elements) |
2289                TransformFlags.ContainsES2015 |
2290                TransformFlags.ContainsBindingPattern;
2291            return node;
2292        }
2293
2294        // @api
2295        function updateArrayBindingPattern(node: ArrayBindingPattern, elements: readonly ArrayBindingElement[]) {
2296            return node.elements !== elements
2297                ? update(createArrayBindingPattern(elements), node)
2298                : node;
2299        }
2300
2301        // @api
2302        function createBindingElement(dotDotDotToken: DotDotDotToken | undefined, propertyName: string | PropertyName | undefined, name: string | BindingName, initializer?: Expression) {
2303            const node = createBaseBindingLikeDeclaration<BindingElement>(
2304                SyntaxKind.BindingElement,
2305                /*modifiers*/ undefined,
2306                name,
2307                initializer && parenthesizerRules().parenthesizeExpressionForDisallowedComma(initializer)
2308            );
2309            node.propertyName = asName(propertyName);
2310            node.dotDotDotToken = dotDotDotToken;
2311            node.transformFlags |=
2312                propagateChildFlags(node.dotDotDotToken) |
2313                TransformFlags.ContainsES2015;
2314            if (node.propertyName) {
2315                node.transformFlags |= isIdentifier(node.propertyName) ?
2316                    propagateIdentifierNameFlags(node.propertyName) :
2317                    propagateChildFlags(node.propertyName);
2318            }
2319            if (dotDotDotToken) node.transformFlags |= TransformFlags.ContainsRestOrSpread;
2320            return node;
2321        }
2322
2323        // @api
2324        function updateBindingElement(node: BindingElement, dotDotDotToken: DotDotDotToken | undefined, propertyName: PropertyName | undefined, name: BindingName, initializer: Expression | undefined) {
2325            return node.propertyName !== propertyName
2326                || node.dotDotDotToken !== dotDotDotToken
2327                || node.name !== name
2328                || node.initializer !== initializer
2329                ? update(createBindingElement(dotDotDotToken, propertyName, name, initializer), node)
2330                : node;
2331        }
2332
2333        //
2334        // Expression
2335        //
2336
2337        function createBaseExpression<T extends Expression>(kind: T["kind"]) {
2338            const node = createBaseNode(kind);
2339            // the following properties are commonly set by the checker/binder
2340            return node;
2341        }
2342
2343        // @api
2344        function createArrayLiteralExpression(elements?: readonly Expression[], multiLine?: boolean) {
2345            const node = createBaseExpression<ArrayLiteralExpression>(SyntaxKind.ArrayLiteralExpression);
2346            // Ensure we add a trailing comma for something like `[NumericLiteral(1), NumericLiteral(2), OmittedExpresion]` so that
2347            // we end up with `[1, 2, ,]` instead of `[1, 2, ]` otherwise the `OmittedExpression` will just end up being treated like
2348            // a trailing comma.
2349            const lastElement = elements && lastOrUndefined(elements);
2350            const elementsArray = createNodeArray(elements, lastElement && isOmittedExpression(lastElement) ? true : undefined);
2351            node.elements = parenthesizerRules().parenthesizeExpressionsOfCommaDelimitedList(elementsArray);
2352            node.multiLine = multiLine;
2353            node.transformFlags |= propagateChildrenFlags(node.elements);
2354            return node;
2355        }
2356
2357        // @api
2358        function updateArrayLiteralExpression(node: ArrayLiteralExpression, elements: readonly Expression[]) {
2359            return node.elements !== elements
2360                ? update(createArrayLiteralExpression(elements, node.multiLine), node)
2361                : node;
2362        }
2363
2364        // @api
2365        function createObjectLiteralExpression(properties?: readonly ObjectLiteralElementLike[], multiLine?: boolean) {
2366            const node = createBaseExpression<ObjectLiteralExpression>(SyntaxKind.ObjectLiteralExpression);
2367            node.properties = createNodeArray(properties);
2368            node.multiLine = multiLine;
2369            node.transformFlags |= propagateChildrenFlags(node.properties);
2370            return node;
2371        }
2372
2373        // @api
2374        function updateObjectLiteralExpression(node: ObjectLiteralExpression, properties: readonly ObjectLiteralElementLike[]) {
2375            return node.properties !== properties
2376                ? update(createObjectLiteralExpression(properties, node.multiLine), node)
2377                : node;
2378        }
2379
2380        // @api
2381        function createPropertyAccessExpression(expression: Expression, name: string | Identifier | PrivateIdentifier) {
2382            const node = createBaseExpression<PropertyAccessExpression>(SyntaxKind.PropertyAccessExpression);
2383            node.expression = parenthesizerRules().parenthesizeLeftSideOfAccess(expression, /*optionalChain*/ false);
2384            node.name = asName(name);
2385            node.transformFlags =
2386                propagateChildFlags(node.expression) |
2387                (isIdentifier(node.name) ?
2388                    propagateIdentifierNameFlags(node.name) :
2389                    propagateChildFlags(node.name) | TransformFlags.ContainsPrivateIdentifierInExpression);
2390            if (isSuperKeyword(expression)) {
2391                // super method calls require a lexical 'this'
2392                // super method calls require 'super' hoisting in ES2017 and ES2018 async functions and async generators
2393                node.transformFlags |=
2394                    TransformFlags.ContainsES2017 |
2395                    TransformFlags.ContainsES2018;
2396            }
2397            return node;
2398        }
2399
2400        // @api
2401        function updatePropertyAccessExpression(node: PropertyAccessExpression, expression: Expression, name: Identifier | PrivateIdentifier) {
2402            if (isPropertyAccessChain(node)) {
2403                return updatePropertyAccessChain(node, expression, node.questionDotToken, cast(name, isIdentifier));
2404            }
2405            return node.expression !== expression
2406                || node.name !== name
2407                ? update(createPropertyAccessExpression(expression, name), node)
2408                : node;
2409        }
2410
2411        // @api
2412        function createPropertyAccessChain(expression: Expression, questionDotToken: QuestionDotToken | undefined, name: string | Identifier | PrivateIdentifier) {
2413            const node = createBaseExpression<PropertyAccessChain>(SyntaxKind.PropertyAccessExpression);
2414            node.flags |= NodeFlags.OptionalChain;
2415            node.expression = parenthesizerRules().parenthesizeLeftSideOfAccess(expression, /*optionalChain*/ true);
2416            node.questionDotToken = questionDotToken;
2417            node.name = asName(name);
2418            node.transformFlags |=
2419                TransformFlags.ContainsES2020 |
2420                propagateChildFlags(node.expression) |
2421                propagateChildFlags(node.questionDotToken) |
2422                (isIdentifier(node.name) ?
2423                    propagateIdentifierNameFlags(node.name) :
2424                    propagateChildFlags(node.name) | TransformFlags.ContainsPrivateIdentifierInExpression);
2425            return node;
2426        }
2427
2428        // @api
2429        function updatePropertyAccessChain(node: PropertyAccessChain, expression: Expression, questionDotToken: QuestionDotToken | undefined, name: Identifier | PrivateIdentifier) {
2430            Debug.assert(!!(node.flags & NodeFlags.OptionalChain), "Cannot update a PropertyAccessExpression using updatePropertyAccessChain. Use updatePropertyAccess instead.");
2431            // Because we are updating an existing PropertyAccessChain we want to inherit its emitFlags
2432            // instead of using the default from createPropertyAccess
2433            return node.expression !== expression
2434                || node.questionDotToken !== questionDotToken
2435                || node.name !== name
2436                ? update(createPropertyAccessChain(expression, questionDotToken, name), node)
2437                : node;
2438        }
2439
2440        // @api
2441        function createElementAccessExpression(expression: Expression, index: number | Expression) {
2442            const node = createBaseExpression<ElementAccessExpression>(SyntaxKind.ElementAccessExpression);
2443            node.expression = parenthesizerRules().parenthesizeLeftSideOfAccess(expression, /*optionalChain*/ false);
2444            node.argumentExpression = asExpression(index);
2445            node.transformFlags |=
2446                propagateChildFlags(node.expression) |
2447                propagateChildFlags(node.argumentExpression);
2448            if (isSuperKeyword(expression)) {
2449                // super method calls require a lexical 'this'
2450                // super method calls require 'super' hoisting in ES2017 and ES2018 async functions and async generators
2451                node.transformFlags |=
2452                    TransformFlags.ContainsES2017 |
2453                    TransformFlags.ContainsES2018;
2454            }
2455            return node;
2456        }
2457
2458        // @api
2459        function updateElementAccessExpression(node: ElementAccessExpression, expression: Expression, argumentExpression: Expression) {
2460            if (isElementAccessChain(node)) {
2461                return updateElementAccessChain(node, expression, node.questionDotToken, argumentExpression);
2462            }
2463            return node.expression !== expression
2464                || node.argumentExpression !== argumentExpression
2465                ? update(createElementAccessExpression(expression, argumentExpression), node)
2466                : node;
2467        }
2468
2469        // @api
2470        function createElementAccessChain(expression: Expression, questionDotToken: QuestionDotToken | undefined, index: number | Expression) {
2471            const node = createBaseExpression<ElementAccessChain>(SyntaxKind.ElementAccessExpression);
2472            node.flags |= NodeFlags.OptionalChain;
2473            node.expression = parenthesizerRules().parenthesizeLeftSideOfAccess(expression, /*optionalChain*/ true);
2474            node.questionDotToken = questionDotToken;
2475            node.argumentExpression = asExpression(index);
2476            node.transformFlags |=
2477                propagateChildFlags(node.expression) |
2478                propagateChildFlags(node.questionDotToken) |
2479                propagateChildFlags(node.argumentExpression) |
2480                TransformFlags.ContainsES2020;
2481            return node;
2482        }
2483
2484        // @api
2485        function updateElementAccessChain(node: ElementAccessChain, expression: Expression, questionDotToken: QuestionDotToken | undefined, argumentExpression: Expression) {
2486            Debug.assert(!!(node.flags & NodeFlags.OptionalChain), "Cannot update a ElementAccessExpression using updateElementAccessChain. Use updateElementAccess instead.");
2487            // Because we are updating an existing ElementAccessChain we want to inherit its emitFlags
2488            // instead of using the default from createElementAccess
2489            return node.expression !== expression
2490                || node.questionDotToken !== questionDotToken
2491                || node.argumentExpression !== argumentExpression
2492                ? update(createElementAccessChain(expression, questionDotToken, argumentExpression), node)
2493                : node;
2494        }
2495
2496        // @api
2497        function createCallExpression(expression: Expression, typeArguments: readonly TypeNode[] | undefined, argumentsArray: readonly Expression[] | undefined) {
2498            const node = createBaseExpression<CallExpression>(SyntaxKind.CallExpression);
2499            node.expression = parenthesizerRules().parenthesizeLeftSideOfAccess(expression, /*optionalChain*/ false);
2500            node.typeArguments = asNodeArray(typeArguments);
2501            node.arguments = parenthesizerRules().parenthesizeExpressionsOfCommaDelimitedList(createNodeArray(argumentsArray));
2502            node.transformFlags |=
2503                propagateChildFlags(node.expression) |
2504                propagateChildrenFlags(node.typeArguments) |
2505                propagateChildrenFlags(node.arguments);
2506            if (node.typeArguments) {
2507                node.transformFlags |= TransformFlags.ContainsTypeScript;
2508            }
2509            if (isImportKeyword(node.expression)) {
2510                node.transformFlags |= TransformFlags.ContainsDynamicImport;
2511            }
2512            else if (isSuperProperty(node.expression)) {
2513                node.transformFlags |= TransformFlags.ContainsLexicalThis;
2514            }
2515            return node;
2516        }
2517
2518        // @api
2519        function updateCallExpression(node: CallExpression, expression: Expression, typeArguments: readonly TypeNode[] | undefined, argumentsArray: readonly Expression[]) {
2520            if (isCallChain(node)) {
2521                return updateCallChain(node, expression, node.questionDotToken, typeArguments, argumentsArray);
2522            }
2523            return node.expression !== expression
2524                || node.typeArguments !== typeArguments
2525                || node.arguments !== argumentsArray
2526                ? update(createCallExpression(expression, typeArguments, argumentsArray), node)
2527                : node;
2528        }
2529
2530        // @api
2531        function createCallChain(expression: Expression, questionDotToken: QuestionDotToken | undefined, typeArguments: readonly TypeNode[] | undefined, argumentsArray: readonly Expression[] | undefined) {
2532            const node = createBaseExpression<CallChain>(SyntaxKind.CallExpression);
2533            node.flags |= NodeFlags.OptionalChain;
2534            node.expression = parenthesizerRules().parenthesizeLeftSideOfAccess(expression, /*optionalChain*/ true);
2535            node.questionDotToken = questionDotToken;
2536            node.typeArguments = asNodeArray(typeArguments);
2537            node.arguments = parenthesizerRules().parenthesizeExpressionsOfCommaDelimitedList(createNodeArray(argumentsArray));
2538            node.transformFlags |=
2539                propagateChildFlags(node.expression) |
2540                propagateChildFlags(node.questionDotToken) |
2541                propagateChildrenFlags(node.typeArguments) |
2542                propagateChildrenFlags(node.arguments) |
2543                TransformFlags.ContainsES2020;
2544            if (node.typeArguments) {
2545                node.transformFlags |= TransformFlags.ContainsTypeScript;
2546            }
2547            if (isSuperProperty(node.expression)) {
2548                node.transformFlags |= TransformFlags.ContainsLexicalThis;
2549            }
2550            return node;
2551        }
2552
2553        // @api
2554        function updateCallChain(node: CallChain, expression: Expression, questionDotToken: QuestionDotToken | undefined, typeArguments: readonly TypeNode[] | undefined, argumentsArray: readonly Expression[]) {
2555            Debug.assert(!!(node.flags & NodeFlags.OptionalChain), "Cannot update a CallExpression using updateCallChain. Use updateCall instead.");
2556            return node.expression !== expression
2557                || node.questionDotToken !== questionDotToken
2558                || node.typeArguments !== typeArguments
2559                || node.arguments !== argumentsArray
2560                ? update(createCallChain(expression, questionDotToken, typeArguments, argumentsArray), node)
2561                : node;
2562        }
2563
2564        // @api
2565        function createNewExpression(expression: Expression, typeArguments: readonly TypeNode[] | undefined, argumentsArray: readonly Expression[] | undefined) {
2566            const node = createBaseExpression<NewExpression>(SyntaxKind.NewExpression);
2567            node.expression = parenthesizerRules().parenthesizeExpressionOfNew(expression);
2568            node.typeArguments = asNodeArray(typeArguments);
2569            node.arguments = argumentsArray ? parenthesizerRules().parenthesizeExpressionsOfCommaDelimitedList(argumentsArray) : undefined;
2570            node.transformFlags |=
2571                propagateChildFlags(node.expression) |
2572                propagateChildrenFlags(node.typeArguments) |
2573                propagateChildrenFlags(node.arguments) |
2574                TransformFlags.ContainsES2020;
2575            if (node.typeArguments) {
2576                node.transformFlags |= TransformFlags.ContainsTypeScript;
2577            }
2578            return node;
2579        }
2580
2581        // @api
2582        function updateNewExpression(node: NewExpression, expression: Expression, typeArguments: readonly TypeNode[] | undefined, argumentsArray: readonly Expression[] | undefined) {
2583            return node.expression !== expression
2584                || node.typeArguments !== typeArguments
2585                || node.arguments !== argumentsArray
2586                ? update(createNewExpression(expression, typeArguments, argumentsArray), node)
2587                : node;
2588        }
2589
2590        // @api
2591        function createTaggedTemplateExpression(tag: Expression, typeArguments: readonly TypeNode[] | undefined, template: TemplateLiteral) {
2592            const node = createBaseExpression<TaggedTemplateExpression>(SyntaxKind.TaggedTemplateExpression);
2593            node.tag = parenthesizerRules().parenthesizeLeftSideOfAccess(tag, /*optionalChain*/ false);
2594            node.typeArguments = asNodeArray(typeArguments);
2595            node.template = template;
2596            node.transformFlags |=
2597                propagateChildFlags(node.tag) |
2598                propagateChildrenFlags(node.typeArguments) |
2599                propagateChildFlags(node.template) |
2600                TransformFlags.ContainsES2015;
2601            if (node.typeArguments) {
2602                node.transformFlags |= TransformFlags.ContainsTypeScript;
2603            }
2604            if (hasInvalidEscape(node.template)) {
2605                node.transformFlags |= TransformFlags.ContainsES2018;
2606            }
2607            return node;
2608        }
2609
2610        // @api
2611        function updateTaggedTemplateExpression(node: TaggedTemplateExpression, tag: Expression, typeArguments: readonly TypeNode[] | undefined, template: TemplateLiteral) {
2612            return node.tag !== tag
2613                || node.typeArguments !== typeArguments
2614                || node.template !== template
2615                ? update(createTaggedTemplateExpression(tag, typeArguments, template), node)
2616                : node;
2617        }
2618
2619        // @api
2620        function createTypeAssertion(type: TypeNode, expression: Expression) {
2621            const node = createBaseExpression<TypeAssertion>(SyntaxKind.TypeAssertionExpression);
2622            node.expression = parenthesizerRules().parenthesizeOperandOfPrefixUnary(expression);
2623            node.type = type;
2624            node.transformFlags |=
2625                propagateChildFlags(node.expression) |
2626                propagateChildFlags(node.type) |
2627                TransformFlags.ContainsTypeScript;
2628            return node;
2629        }
2630
2631        // @api
2632        function updateTypeAssertion(node: TypeAssertion, type: TypeNode, expression: Expression) {
2633            return node.type !== type
2634                || node.expression !== expression
2635                ? update(createTypeAssertion(type, expression), node)
2636                : node;
2637        }
2638
2639        // @api
2640        function createParenthesizedExpression(expression: Expression) {
2641            const node = createBaseExpression<ParenthesizedExpression>(SyntaxKind.ParenthesizedExpression);
2642            node.expression = expression;
2643            node.transformFlags = propagateChildFlags(node.expression);
2644            return node;
2645        }
2646
2647        // @api
2648        function updateParenthesizedExpression(node: ParenthesizedExpression, expression: Expression) {
2649            return node.expression !== expression
2650                ? update(createParenthesizedExpression(expression), node)
2651                : node;
2652        }
2653
2654        // @api
2655        function createFunctionExpression(
2656            modifiers: readonly ModifierLike[] | undefined,
2657            asteriskToken: AsteriskToken | undefined,
2658            name: string | Identifier | undefined,
2659            typeParameters: readonly TypeParameterDeclaration[] | undefined,
2660            parameters: readonly ParameterDeclaration[] | undefined,
2661            type: TypeNode | undefined,
2662            body: Block
2663        ) {
2664            const node = createBaseFunctionLikeDeclaration<FunctionExpression>(
2665                SyntaxKind.FunctionExpression,
2666                modifiers,
2667                name,
2668                typeParameters,
2669                parameters,
2670                type,
2671                body
2672            );
2673            node.asteriskToken = asteriskToken;
2674            node.transformFlags |= propagateChildFlags(node.asteriskToken);
2675            if (node.typeParameters) {
2676                node.transformFlags |= TransformFlags.ContainsTypeScript;
2677            }
2678            if (modifiersToFlags(node.modifiers) & ModifierFlags.Async) {
2679                if (node.asteriskToken) {
2680                    node.transformFlags |= TransformFlags.ContainsES2018;
2681                }
2682                else {
2683                    node.transformFlags |= TransformFlags.ContainsES2017;
2684                }
2685            }
2686            else if (node.asteriskToken) {
2687                node.transformFlags |= TransformFlags.ContainsGenerator;
2688            }
2689            return node;
2690        }
2691
2692        // @api
2693        function updateFunctionExpression(
2694            node: FunctionExpression,
2695            modifiers: readonly ModifierLike[] | undefined,
2696            asteriskToken: AsteriskToken | undefined,
2697            name: Identifier | undefined,
2698            typeParameters: readonly TypeParameterDeclaration[] | undefined,
2699            parameters: readonly ParameterDeclaration[],
2700            type: TypeNode | undefined,
2701            body: Block
2702        ) {
2703            return node.name !== name
2704                || node.modifiers !== modifiers
2705                || node.asteriskToken !== asteriskToken
2706                || node.typeParameters !== typeParameters
2707                || node.parameters !== parameters
2708                || node.type !== type
2709                || node.body !== body
2710                ? finishUpdateBaseSignatureDeclaration(createFunctionExpression(modifiers, asteriskToken, name, typeParameters, parameters, type, body), node)
2711                : node;
2712        }
2713
2714        // @api
2715        function createEtsComponentExpression(
2716            name: Expression,
2717            argumentsArray: readonly Expression[] | undefined,
2718            body: Block | undefined
2719        ) {
2720            const node = createBaseExpression<EtsComponentExpression>(SyntaxKind.EtsComponentExpression);
2721            node.expression = parenthesizerRules().parenthesizeLeftSideOfAccess(name);
2722            node.arguments = parenthesizerRules().parenthesizeExpressionsOfCommaDelimitedList(createNodeArray(argumentsArray));
2723            node.body = body;
2724            return node;
2725        }
2726
2727        // @api
2728        function updateEtsComponentExpression(
2729            node: EtsComponentExpression,
2730            name: Expression,
2731            argumentsArray: readonly Expression[] | undefined,
2732            body: Block | undefined
2733        ) {
2734            return node.expression !== name
2735                || node.arguments !== argumentsArray
2736                || node.body !== body
2737                ? createEtsComponentExpression(name, argumentsArray, body)
2738                : node;
2739        }
2740
2741        // @api
2742        function createArrowFunction(
2743            modifiers: readonly ModifierLike[] | undefined,
2744            typeParameters: readonly TypeParameterDeclaration[] | undefined,
2745            parameters: readonly ParameterDeclaration[],
2746            type: TypeNode | undefined,
2747            equalsGreaterThanToken: EqualsGreaterThanToken | undefined,
2748            body: ConciseBody
2749        ) {
2750            const node = createBaseFunctionLikeDeclaration<ArrowFunction>(
2751                SyntaxKind.ArrowFunction,
2752                modifiers,
2753                /*name*/ undefined,
2754                typeParameters,
2755                parameters,
2756                type,
2757                parenthesizerRules().parenthesizeConciseBodyOfArrowFunction(body)
2758            );
2759            node.equalsGreaterThanToken = equalsGreaterThanToken ?? createToken(SyntaxKind.EqualsGreaterThanToken);
2760            node.transformFlags |=
2761                propagateChildFlags(node.equalsGreaterThanToken) |
2762                TransformFlags.ContainsES2015;
2763            if (modifiersToFlags(node.modifiers) & ModifierFlags.Async) {
2764                node.transformFlags |= TransformFlags.ContainsES2017 | TransformFlags.ContainsLexicalThis;
2765            }
2766            return node;
2767        }
2768
2769        // @api
2770        function updateArrowFunction(
2771            node: ArrowFunction,
2772            modifiers: readonly ModifierLike[] | undefined,
2773            typeParameters: readonly TypeParameterDeclaration[] | undefined,
2774            parameters: readonly ParameterDeclaration[],
2775            type: TypeNode | undefined,
2776            equalsGreaterThanToken: EqualsGreaterThanToken,
2777            body: ConciseBody
2778        ): ArrowFunction {
2779            return node.modifiers !== modifiers
2780                || node.typeParameters !== typeParameters
2781                || node.parameters !== parameters
2782                || node.type !== type
2783                || node.equalsGreaterThanToken !== equalsGreaterThanToken
2784                || node.body !== body
2785                ? finishUpdateBaseSignatureDeclaration(createArrowFunction(modifiers, typeParameters, parameters, type, equalsGreaterThanToken, body), node)
2786                : node;
2787        }
2788
2789        // @api
2790        function createDeleteExpression(expression: Expression) {
2791            const node = createBaseExpression<DeleteExpression>(SyntaxKind.DeleteExpression);
2792            node.expression = parenthesizerRules().parenthesizeOperandOfPrefixUnary(expression);
2793            node.transformFlags |= propagateChildFlags(node.expression);
2794            return node;
2795        }
2796
2797        // @api
2798        function updateDeleteExpression(node: DeleteExpression, expression: Expression) {
2799            return node.expression !== expression
2800                ? update(createDeleteExpression(expression), node)
2801                : node;
2802        }
2803
2804        // @api
2805        function createTypeOfExpression(expression: Expression) {
2806            const node = createBaseExpression<TypeOfExpression>(SyntaxKind.TypeOfExpression);
2807            node.expression = parenthesizerRules().parenthesizeOperandOfPrefixUnary(expression);
2808            node.transformFlags |= propagateChildFlags(node.expression);
2809            return node;
2810        }
2811
2812        // @api
2813        function updateTypeOfExpression(node: TypeOfExpression, expression: Expression) {
2814            return node.expression !== expression
2815                ? update(createTypeOfExpression(expression), node)
2816                : node;
2817        }
2818
2819        // @api
2820        function createVoidExpression(expression: Expression) {
2821            const node = createBaseExpression<VoidExpression>(SyntaxKind.VoidExpression);
2822            node.expression = parenthesizerRules().parenthesizeOperandOfPrefixUnary(expression);
2823            node.transformFlags |= propagateChildFlags(node.expression);
2824            return node;
2825        }
2826
2827        // @api
2828        function updateVoidExpression(node: VoidExpression, expression: Expression) {
2829            return node.expression !== expression
2830                ? update(createVoidExpression(expression), node)
2831                : node;
2832        }
2833
2834        // @api
2835        function createAwaitExpression(expression: Expression) {
2836            const node = createBaseExpression<AwaitExpression>(SyntaxKind.AwaitExpression);
2837            node.expression = parenthesizerRules().parenthesizeOperandOfPrefixUnary(expression);
2838            node.transformFlags |=
2839                propagateChildFlags(node.expression) |
2840                TransformFlags.ContainsES2017 |
2841                TransformFlags.ContainsES2018 |
2842                TransformFlags.ContainsAwait;
2843            return node;
2844        }
2845
2846        // @api
2847        function updateAwaitExpression(node: AwaitExpression, expression: Expression) {
2848            return node.expression !== expression
2849                ? update(createAwaitExpression(expression), node)
2850                : node;
2851        }
2852
2853        // @api
2854        function createPrefixUnaryExpression(operator: PrefixUnaryOperator, operand: Expression) {
2855            const node = createBaseExpression<PrefixUnaryExpression>(SyntaxKind.PrefixUnaryExpression);
2856            node.operator = operator;
2857            node.operand = parenthesizerRules().parenthesizeOperandOfPrefixUnary(operand);
2858            node.transformFlags |= propagateChildFlags(node.operand);
2859            // Only set this flag for non-generated identifiers and non-"local" names. See the
2860            // comment in `visitPreOrPostfixUnaryExpression` in module.ts
2861            if ((operator === SyntaxKind.PlusPlusToken || operator === SyntaxKind.MinusMinusToken) &&
2862                isIdentifier(node.operand) &&
2863                !isGeneratedIdentifier(node.operand) &&
2864                !isLocalName(node.operand)) {
2865                node.transformFlags |= TransformFlags.ContainsUpdateExpressionForIdentifier;
2866            }
2867            return node;
2868        }
2869
2870        // @api
2871        function updatePrefixUnaryExpression(node: PrefixUnaryExpression, operand: Expression) {
2872            return node.operand !== operand
2873                ? update(createPrefixUnaryExpression(node.operator, operand), node)
2874                : node;
2875        }
2876
2877        // @api
2878        function createPostfixUnaryExpression(operand: Expression, operator: PostfixUnaryOperator) {
2879            const node = createBaseExpression<PostfixUnaryExpression>(SyntaxKind.PostfixUnaryExpression);
2880            node.operator = operator;
2881            node.operand = parenthesizerRules().parenthesizeOperandOfPostfixUnary(operand);
2882            node.transformFlags |= propagateChildFlags(node.operand);
2883            // Only set this flag for non-generated identifiers and non-"local" names. See the
2884            // comment in `visitPreOrPostfixUnaryExpression` in module.ts
2885            if (isIdentifier(node.operand) &&
2886                !isGeneratedIdentifier(node.operand) &&
2887                !isLocalName(node.operand)) {
2888                node.transformFlags |= TransformFlags.ContainsUpdateExpressionForIdentifier;
2889            }
2890            return node;
2891        }
2892
2893        // @api
2894        function updatePostfixUnaryExpression(node: PostfixUnaryExpression, operand: Expression) {
2895            return node.operand !== operand
2896                ? update(createPostfixUnaryExpression(operand, node.operator), node)
2897                : node;
2898        }
2899
2900        // @api
2901        function createBinaryExpression(left: Expression, operator: BinaryOperator | BinaryOperatorToken, right: Expression) {
2902            const node = createBaseExpression<BinaryExpression>(SyntaxKind.BinaryExpression);
2903            const operatorToken = asToken(operator);
2904            const operatorKind = operatorToken.kind;
2905            node.left = parenthesizerRules().parenthesizeLeftSideOfBinary(operatorKind, left);
2906            node.operatorToken = operatorToken;
2907            node.right = parenthesizerRules().parenthesizeRightSideOfBinary(operatorKind, node.left, right);
2908            node.transformFlags |=
2909                propagateChildFlags(node.left) |
2910                propagateChildFlags(node.operatorToken) |
2911                propagateChildFlags(node.right);
2912            if (operatorKind === SyntaxKind.QuestionQuestionToken) {
2913                node.transformFlags |= TransformFlags.ContainsES2020;
2914            }
2915            else if (operatorKind === SyntaxKind.EqualsToken) {
2916                if (isObjectLiteralExpression(node.left)) {
2917                    node.transformFlags |=
2918                        TransformFlags.ContainsES2015 |
2919                        TransformFlags.ContainsES2018 |
2920                        TransformFlags.ContainsDestructuringAssignment |
2921                        propagateAssignmentPatternFlags(node.left);
2922                }
2923                else if (isArrayLiteralExpression(node.left)) {
2924                    node.transformFlags |=
2925                        TransformFlags.ContainsES2015 |
2926                        TransformFlags.ContainsDestructuringAssignment |
2927                        propagateAssignmentPatternFlags(node.left);
2928                }
2929            }
2930            else if (operatorKind === SyntaxKind.AsteriskAsteriskToken || operatorKind === SyntaxKind.AsteriskAsteriskEqualsToken) {
2931                node.transformFlags |= TransformFlags.ContainsES2016;
2932            }
2933            else if (isLogicalOrCoalescingAssignmentOperator(operatorKind)) {
2934                node.transformFlags |= TransformFlags.ContainsES2021;
2935            }
2936            if (operatorKind === SyntaxKind.InKeyword && isPrivateIdentifier(node.left)) {
2937                node.transformFlags |= TransformFlags.ContainsPrivateIdentifierInExpression;
2938            }
2939            return node;
2940        }
2941
2942        function propagateAssignmentPatternFlags(node: AssignmentPattern): TransformFlags {
2943            if (node.transformFlags & TransformFlags.ContainsObjectRestOrSpread) return TransformFlags.ContainsObjectRestOrSpread;
2944            if (node.transformFlags & TransformFlags.ContainsES2018) {
2945                // check for nested spread assignments, otherwise '{ x: { a, ...b } = foo } = c'
2946                // will not be correctly interpreted by the ES2018 transformer
2947                for (const element of getElementsOfBindingOrAssignmentPattern(node)) {
2948                    const target = getTargetOfBindingOrAssignmentElement(element);
2949                    if (target && isAssignmentPattern(target)) {
2950                        if (target.transformFlags & TransformFlags.ContainsObjectRestOrSpread) {
2951                            return TransformFlags.ContainsObjectRestOrSpread;
2952                        }
2953                        if (target.transformFlags & TransformFlags.ContainsES2018) {
2954                            const flags = propagateAssignmentPatternFlags(target);
2955                            if (flags) return flags;
2956                        }
2957                    }
2958                }
2959            }
2960            return TransformFlags.None;
2961        }
2962
2963        // @api
2964        function updateBinaryExpression(node: BinaryExpression, left: Expression, operator: BinaryOperatorToken, right: Expression) {
2965            return node.left !== left
2966                || node.operatorToken !== operator
2967                || node.right !== right
2968                ? update(createBinaryExpression(left, operator, right), node)
2969                : node;
2970        }
2971
2972        // @api
2973        function createConditionalExpression(condition: Expression, questionToken: QuestionToken | undefined, whenTrue: Expression, colonToken: ColonToken | undefined, whenFalse: Expression) {
2974            const node = createBaseExpression<ConditionalExpression>(SyntaxKind.ConditionalExpression);
2975            node.condition = parenthesizerRules().parenthesizeConditionOfConditionalExpression(condition);
2976            node.questionToken = questionToken ?? createToken(SyntaxKind.QuestionToken);
2977            node.whenTrue = parenthesizerRules().parenthesizeBranchOfConditionalExpression(whenTrue);
2978            node.colonToken = colonToken ?? createToken(SyntaxKind.ColonToken);
2979            node.whenFalse = parenthesizerRules().parenthesizeBranchOfConditionalExpression(whenFalse);
2980            node.transformFlags |=
2981                propagateChildFlags(node.condition) |
2982                propagateChildFlags(node.questionToken) |
2983                propagateChildFlags(node.whenTrue) |
2984                propagateChildFlags(node.colonToken) |
2985                propagateChildFlags(node.whenFalse);
2986            return node;
2987        }
2988
2989        // @api
2990        function updateConditionalExpression(
2991            node: ConditionalExpression,
2992            condition: Expression,
2993            questionToken: Token<SyntaxKind.QuestionToken>,
2994            whenTrue: Expression,
2995            colonToken: Token<SyntaxKind.ColonToken>,
2996            whenFalse: Expression
2997        ): ConditionalExpression {
2998            return node.condition !== condition
2999                || node.questionToken !== questionToken
3000                || node.whenTrue !== whenTrue
3001                || node.colonToken !== colonToken
3002                || node.whenFalse !== whenFalse
3003                ? update(createConditionalExpression(condition, questionToken, whenTrue, colonToken, whenFalse), node)
3004                : node;
3005        }
3006
3007        // @api
3008        function createTemplateExpression(head: TemplateHead, templateSpans: readonly TemplateSpan[]) {
3009            const node = createBaseExpression<TemplateExpression>(SyntaxKind.TemplateExpression);
3010            node.head = head;
3011            node.templateSpans = createNodeArray(templateSpans);
3012            node.transformFlags |=
3013                propagateChildFlags(node.head) |
3014                propagateChildrenFlags(node.templateSpans) |
3015                TransformFlags.ContainsES2015;
3016            return node;
3017        }
3018
3019        // @api
3020        function updateTemplateExpression(node: TemplateExpression, head: TemplateHead, templateSpans: readonly TemplateSpan[]) {
3021            return node.head !== head
3022                || node.templateSpans !== templateSpans
3023                ? update(createTemplateExpression(head, templateSpans), node)
3024                : node;
3025        }
3026
3027        function createTemplateLiteralLikeNodeChecked(kind: TemplateLiteralToken["kind"], text: string | undefined, rawText: string | undefined, templateFlags = TokenFlags.None) {
3028            Debug.assert(!(templateFlags & ~TokenFlags.TemplateLiteralLikeFlags), "Unsupported template flags.");
3029            // NOTE: without the assignment to `undefined`, we don't narrow the initial type of `cooked`.
3030            // eslint-disable-next-line no-undef-init
3031            let cooked: string | object | undefined = undefined;
3032            if (rawText !== undefined && rawText !== text) {
3033                cooked = getCookedText(kind, rawText);
3034                if (typeof cooked === "object") {
3035                    return Debug.fail("Invalid raw text");
3036                }
3037            }
3038            if (text === undefined) {
3039                if (cooked === undefined) {
3040                    return Debug.fail("Arguments 'text' and 'rawText' may not both be undefined.");
3041                }
3042                text = cooked;
3043            }
3044            else if (cooked !== undefined) {
3045                Debug.assert(text === cooked, "Expected argument 'text' to be the normalized (i.e. 'cooked') version of argument 'rawText'.");
3046            }
3047            return createTemplateLiteralLikeNode(kind, text, rawText, templateFlags);
3048        }
3049
3050        // @api
3051        function createTemplateLiteralLikeNode(kind: TemplateLiteralToken["kind"], text: string, rawText: string | undefined, templateFlags: TokenFlags | undefined) {
3052            const node = createBaseToken<TemplateLiteralLikeNode>(kind);
3053            node.text = text;
3054            node.rawText = rawText;
3055            node.templateFlags = templateFlags! & TokenFlags.TemplateLiteralLikeFlags;
3056            node.transformFlags |= TransformFlags.ContainsES2015;
3057            if (node.templateFlags) {
3058                node.transformFlags |= TransformFlags.ContainsES2018;
3059            }
3060            return node;
3061        }
3062
3063        // @api
3064        function createTemplateHead(text: string | undefined, rawText?: string, templateFlags?: TokenFlags) {
3065            return createTemplateLiteralLikeNodeChecked(SyntaxKind.TemplateHead, text, rawText, templateFlags) as TemplateHead;
3066        }
3067
3068        // @api
3069        function createTemplateMiddle(text: string | undefined, rawText?: string, templateFlags?: TokenFlags) {
3070            return createTemplateLiteralLikeNodeChecked(SyntaxKind.TemplateMiddle, text, rawText, templateFlags) as TemplateMiddle;
3071        }
3072
3073        // @api
3074        function createTemplateTail(text: string | undefined, rawText?: string, templateFlags?: TokenFlags) {
3075            return createTemplateLiteralLikeNodeChecked(SyntaxKind.TemplateTail, text, rawText, templateFlags) as TemplateTail;
3076        }
3077
3078        // @api
3079        function createNoSubstitutionTemplateLiteral(text: string | undefined, rawText?: string, templateFlags?: TokenFlags) {
3080            return createTemplateLiteralLikeNodeChecked(SyntaxKind.NoSubstitutionTemplateLiteral, text, rawText, templateFlags) as NoSubstitutionTemplateLiteral;
3081        }
3082
3083        // @api
3084        function createYieldExpression(asteriskToken: AsteriskToken | undefined, expression: Expression | undefined): YieldExpression {
3085            Debug.assert(!asteriskToken || !!expression, "A `YieldExpression` with an asteriskToken must have an expression.");
3086            const node = createBaseExpression<YieldExpression>(SyntaxKind.YieldExpression);
3087            node.expression = expression && parenthesizerRules().parenthesizeExpressionForDisallowedComma(expression);
3088            node.asteriskToken = asteriskToken;
3089            node.transformFlags |=
3090                propagateChildFlags(node.expression) |
3091                propagateChildFlags(node.asteriskToken) |
3092                TransformFlags.ContainsES2015 |
3093                TransformFlags.ContainsES2018 |
3094                TransformFlags.ContainsYield;
3095            return node;
3096        }
3097
3098        // @api
3099        function updateYieldExpression(node: YieldExpression, asteriskToken: AsteriskToken | undefined, expression: Expression) {
3100            return node.expression !== expression
3101                || node.asteriskToken !== asteriskToken
3102                ? update(createYieldExpression(asteriskToken, expression), node)
3103                : node;
3104        }
3105
3106        // @api
3107        function createSpreadElement(expression: Expression) {
3108            const node = createBaseExpression<SpreadElement>(SyntaxKind.SpreadElement);
3109            node.expression = parenthesizerRules().parenthesizeExpressionForDisallowedComma(expression);
3110            node.transformFlags |=
3111                propagateChildFlags(node.expression) |
3112                TransformFlags.ContainsES2015 |
3113                TransformFlags.ContainsRestOrSpread;
3114            return node;
3115        }
3116
3117        // @api
3118        function updateSpreadElement(node: SpreadElement, expression: Expression) {
3119            return node.expression !== expression
3120                ? update(createSpreadElement(expression), node)
3121                : node;
3122        }
3123
3124        // @api
3125        function createClassExpression(
3126            modifiers: readonly ModifierLike[] | undefined,
3127            name: string | Identifier | undefined,
3128            typeParameters: readonly TypeParameterDeclaration[] | undefined,
3129            heritageClauses: readonly HeritageClause[] | undefined,
3130            members: readonly ClassElement[]
3131        ) {
3132            const node = createBaseClassLikeDeclaration<ClassExpression>(
3133                SyntaxKind.ClassExpression,
3134                modifiers,
3135                name,
3136                typeParameters,
3137                heritageClauses,
3138                members
3139            );
3140            node.transformFlags |= TransformFlags.ContainsES2015;
3141            return node;
3142        }
3143
3144        // @api
3145        function updateClassExpression(
3146            node: ClassExpression,
3147            modifiers: readonly ModifierLike[] | undefined,
3148            name: Identifier | undefined,
3149            typeParameters: readonly TypeParameterDeclaration[] | undefined,
3150            heritageClauses: readonly HeritageClause[] | undefined,
3151            members: readonly ClassElement[]
3152        ) {
3153            return node.modifiers !== modifiers
3154                || node.name !== name
3155                || node.typeParameters !== typeParameters
3156                || node.heritageClauses !== heritageClauses
3157                || node.members !== members
3158                ? update(createClassExpression(modifiers, name, typeParameters, heritageClauses, members), node)
3159                : node;
3160        }
3161
3162        // @api
3163        function createOmittedExpression() {
3164            return createBaseExpression<OmittedExpression>(SyntaxKind.OmittedExpression);
3165        }
3166
3167        // @api
3168        function createExpressionWithTypeArguments(expression: Expression, typeArguments: readonly TypeNode[] | undefined) {
3169            const node = createBaseNode<ExpressionWithTypeArguments>(SyntaxKind.ExpressionWithTypeArguments);
3170            node.expression = parenthesizerRules().parenthesizeLeftSideOfAccess(expression, /*optionalChain*/ false);
3171            node.typeArguments = typeArguments && parenthesizerRules().parenthesizeTypeArguments(typeArguments);
3172            node.transformFlags |=
3173                propagateChildFlags(node.expression) |
3174                propagateChildrenFlags(node.typeArguments) |
3175                TransformFlags.ContainsES2015;
3176            return node;
3177        }
3178
3179        // @api
3180        function updateExpressionWithTypeArguments(node: ExpressionWithTypeArguments, expression: Expression, typeArguments: readonly TypeNode[] | undefined) {
3181            return node.expression !== expression
3182                || node.typeArguments !== typeArguments
3183                ? update(createExpressionWithTypeArguments(expression, typeArguments), node)
3184                : node;
3185        }
3186
3187        // @api
3188        function createAsExpression(expression: Expression, type: TypeNode) {
3189            const node = createBaseExpression<AsExpression>(SyntaxKind.AsExpression);
3190            node.expression = expression;
3191            node.type = type;
3192            node.transformFlags |=
3193                propagateChildFlags(node.expression) |
3194                propagateChildFlags(node.type) |
3195                TransformFlags.ContainsTypeScript;
3196            return node;
3197        }
3198
3199        // @api
3200        function updateAsExpression(node: AsExpression, expression: Expression, type: TypeNode) {
3201            return node.expression !== expression
3202                || node.type !== type
3203                ? update(createAsExpression(expression, type), node)
3204                : node;
3205        }
3206
3207        // @api
3208        function createNonNullExpression(expression: Expression) {
3209            const node = createBaseExpression<NonNullExpression>(SyntaxKind.NonNullExpression);
3210            node.expression = parenthesizerRules().parenthesizeLeftSideOfAccess(expression, /*optionalChain*/ false);
3211            node.transformFlags |=
3212                propagateChildFlags(node.expression) |
3213                TransformFlags.ContainsTypeScript;
3214            return node;
3215        }
3216
3217        // @api
3218        function updateNonNullExpression(node: NonNullExpression, expression: Expression) {
3219            if (isNonNullChain(node)) {
3220                return updateNonNullChain(node, expression);
3221            }
3222            return node.expression !== expression
3223                ? update(createNonNullExpression(expression), node)
3224                : node;
3225        }
3226
3227        // @api
3228        function createSatisfiesExpression(expression: Expression, type: TypeNode) {
3229            const node = createBaseExpression<SatisfiesExpression>(SyntaxKind.SatisfiesExpression);
3230            node.expression = expression;
3231            node.type = type;
3232            node.transformFlags |=
3233                propagateChildFlags(node.expression) |
3234                propagateChildFlags(node.type) |
3235                TransformFlags.ContainsTypeScript;
3236            return node;
3237        }
3238
3239        // @api
3240        function updateSatisfiesExpression(node: SatisfiesExpression, expression: Expression, type: TypeNode) {
3241            return node.expression !== expression
3242                || node.type !== type
3243                ? update(createSatisfiesExpression(expression, type), node)
3244                : node;
3245        }
3246
3247        // @api
3248        function createNonNullChain(expression: Expression) {
3249            const node = createBaseExpression<NonNullChain>(SyntaxKind.NonNullExpression);
3250            node.flags |= NodeFlags.OptionalChain;
3251            node.expression = parenthesizerRules().parenthesizeLeftSideOfAccess(expression, /*optionalChain*/ true);
3252            node.transformFlags |=
3253                propagateChildFlags(node.expression) |
3254                TransformFlags.ContainsTypeScript;
3255            return node;
3256        }
3257
3258        // @api
3259        function updateNonNullChain(node: NonNullChain, expression: Expression) {
3260            Debug.assert(!!(node.flags & NodeFlags.OptionalChain), "Cannot update a NonNullExpression using updateNonNullChain. Use updateNonNullExpression instead.");
3261            return node.expression !== expression
3262                ? update(createNonNullChain(expression), node)
3263                : node;
3264        }
3265
3266        // @api
3267        function createMetaProperty(keywordToken: MetaProperty["keywordToken"], name: Identifier) {
3268            const node = createBaseExpression<MetaProperty>(SyntaxKind.MetaProperty);
3269            node.keywordToken = keywordToken;
3270            node.name = name;
3271            node.transformFlags |= propagateChildFlags(node.name);
3272            switch (keywordToken) {
3273                case SyntaxKind.NewKeyword:
3274                    node.transformFlags |= TransformFlags.ContainsES2015;
3275                    break;
3276                case SyntaxKind.ImportKeyword:
3277                    node.transformFlags |= TransformFlags.ContainsESNext;
3278                    break;
3279                default:
3280                    return Debug.assertNever(keywordToken);
3281            }
3282            return node;
3283        }
3284
3285        // @api
3286        function updateMetaProperty(node: MetaProperty, name: Identifier) {
3287            return node.name !== name
3288                ? update(createMetaProperty(node.keywordToken, name), node)
3289                : node;
3290        }
3291
3292        //
3293        // Misc
3294        //
3295
3296        // @api
3297        function createTemplateSpan(expression: Expression, literal: TemplateMiddle | TemplateTail) {
3298            const node = createBaseNode<TemplateSpan>(SyntaxKind.TemplateSpan);
3299            node.expression = expression;
3300            node.literal = literal;
3301            node.transformFlags |=
3302                propagateChildFlags(node.expression) |
3303                propagateChildFlags(node.literal) |
3304                TransformFlags.ContainsES2015;
3305            return node;
3306        }
3307
3308        // @api
3309        function updateTemplateSpan(node: TemplateSpan, expression: Expression, literal: TemplateMiddle | TemplateTail) {
3310            return node.expression !== expression
3311                || node.literal !== literal
3312                ? update(createTemplateSpan(expression, literal), node)
3313                : node;
3314        }
3315
3316        // @api
3317        function createSemicolonClassElement() {
3318            const node = createBaseNode<SemicolonClassElement>(SyntaxKind.SemicolonClassElement);
3319            node.transformFlags |= TransformFlags.ContainsES2015;
3320            return node;
3321        }
3322
3323        //
3324        // Element
3325        //
3326
3327        // @api
3328        function createBlock(statements: readonly Statement[], multiLine?: boolean): Block {
3329            const node = createBaseNode<Block>(SyntaxKind.Block);
3330            node.statements = createNodeArray(statements);
3331            node.multiLine = multiLine;
3332            node.transformFlags |= propagateChildrenFlags(node.statements);
3333            return node;
3334        }
3335
3336        // @api
3337        function updateBlock(node: Block, statements: readonly Statement[]) {
3338            return node.statements !== statements
3339                ? update(createBlock(statements, node.multiLine), node)
3340                : node;
3341        }
3342
3343        // @api
3344        function createVariableStatement(modifiers: readonly Modifier[] | undefined, declarationList: VariableDeclarationList | readonly VariableDeclaration[]) {
3345            const node = createBaseDeclaration<VariableStatement>(SyntaxKind.VariableStatement);
3346            node.modifiers = asNodeArray(modifiers);
3347            node.declarationList = isArray(declarationList) ? createVariableDeclarationList(declarationList) : declarationList;
3348            node.transformFlags |=
3349                propagateChildrenFlags(node.modifiers) |
3350                propagateChildFlags(node.declarationList);
3351            if (modifiersToFlags(node.modifiers) & ModifierFlags.Ambient) {
3352                node.transformFlags = TransformFlags.ContainsTypeScript;
3353            }
3354            return node;
3355        }
3356
3357        // @api
3358        function updateVariableStatement(node: VariableStatement, modifiers: readonly Modifier[] | undefined, declarationList: VariableDeclarationList) {
3359            return node.modifiers !== modifiers
3360                || node.declarationList !== declarationList
3361                ? update(createVariableStatement(modifiers, declarationList), node)
3362                : node;
3363        }
3364
3365        // @api
3366        function createEmptyStatement() {
3367            return createBaseNode<EmptyStatement>(SyntaxKind.EmptyStatement);
3368        }
3369
3370        // @api
3371        function createExpressionStatement(expression: Expression): ExpressionStatement {
3372            const node = createBaseNode<ExpressionStatement>(SyntaxKind.ExpressionStatement);
3373            node.expression = parenthesizerRules().parenthesizeExpressionOfExpressionStatement(expression);
3374            node.transformFlags |= propagateChildFlags(node.expression);
3375            return node;
3376        }
3377
3378        // @api
3379        function updateExpressionStatement(node: ExpressionStatement, expression: Expression) {
3380            return node.expression !== expression
3381                ? update(createExpressionStatement(expression), node)
3382                : node;
3383        }
3384
3385        // @api
3386        function createIfStatement(expression: Expression, thenStatement: Statement, elseStatement?: Statement) {
3387            const node = createBaseNode<IfStatement>(SyntaxKind.IfStatement);
3388            node.expression = expression;
3389            node.thenStatement = asEmbeddedStatement(thenStatement);
3390            node.elseStatement = asEmbeddedStatement(elseStatement);
3391            node.transformFlags |=
3392                propagateChildFlags(node.expression) |
3393                propagateChildFlags(node.thenStatement) |
3394                propagateChildFlags(node.elseStatement);
3395            return node;
3396        }
3397
3398        // @api
3399        function updateIfStatement(node: IfStatement, expression: Expression, thenStatement: Statement, elseStatement: Statement | undefined) {
3400            return node.expression !== expression
3401                || node.thenStatement !== thenStatement
3402                || node.elseStatement !== elseStatement
3403                ? update(createIfStatement(expression, thenStatement, elseStatement), node)
3404                : node;
3405        }
3406
3407        // @api
3408        function createDoStatement(statement: Statement, expression: Expression) {
3409            const node = createBaseNode<DoStatement>(SyntaxKind.DoStatement);
3410            node.statement = asEmbeddedStatement(statement);
3411            node.expression = expression;
3412            node.transformFlags |=
3413                propagateChildFlags(node.statement) |
3414                propagateChildFlags(node.expression);
3415            return node;
3416        }
3417
3418        // @api
3419        function updateDoStatement(node: DoStatement, statement: Statement, expression: Expression) {
3420            return node.statement !== statement
3421                || node.expression !== expression
3422                ? update(createDoStatement(statement, expression), node)
3423                : node;
3424        }
3425
3426        // @api
3427        function createWhileStatement(expression: Expression, statement: Statement) {
3428            const node = createBaseNode<WhileStatement>(SyntaxKind.WhileStatement);
3429            node.expression = expression;
3430            node.statement = asEmbeddedStatement(statement);
3431            node.transformFlags |=
3432                propagateChildFlags(node.expression) |
3433                propagateChildFlags(node.statement);
3434            return node;
3435        }
3436
3437        // @api
3438        function updateWhileStatement(node: WhileStatement, expression: Expression, statement: Statement) {
3439            return node.expression !== expression
3440                || node.statement !== statement
3441                ? update(createWhileStatement(expression, statement), node)
3442                : node;
3443        }
3444
3445        // @api
3446        function createForStatement(initializer: ForInitializer | undefined, condition: Expression | undefined, incrementor: Expression | undefined, statement: Statement) {
3447            const node = createBaseNode<ForStatement>(SyntaxKind.ForStatement);
3448            node.initializer = initializer;
3449            node.condition = condition;
3450            node.incrementor = incrementor;
3451            node.statement = asEmbeddedStatement(statement);
3452            node.transformFlags |=
3453                propagateChildFlags(node.initializer) |
3454                propagateChildFlags(node.condition) |
3455                propagateChildFlags(node.incrementor) |
3456                propagateChildFlags(node.statement);
3457            return node;
3458        }
3459
3460        // @api
3461        function updateForStatement(node: ForStatement, initializer: ForInitializer | undefined, condition: Expression | undefined, incrementor: Expression | undefined, statement: Statement) {
3462            return node.initializer !== initializer
3463                || node.condition !== condition
3464                || node.incrementor !== incrementor
3465                || node.statement !== statement
3466                ? update(createForStatement(initializer, condition, incrementor, statement), node)
3467                : node;
3468        }
3469
3470        // @api
3471        function createForInStatement(initializer: ForInitializer, expression: Expression, statement: Statement) {
3472            const node = createBaseNode<ForInStatement>(SyntaxKind.ForInStatement);
3473            node.initializer = initializer;
3474            node.expression = expression;
3475            node.statement = asEmbeddedStatement(statement);
3476            node.transformFlags |=
3477                propagateChildFlags(node.initializer) |
3478                propagateChildFlags(node.expression) |
3479                propagateChildFlags(node.statement);
3480            return node;
3481        }
3482
3483        // @api
3484        function updateForInStatement(node: ForInStatement, initializer: ForInitializer, expression: Expression, statement: Statement) {
3485            return node.initializer !== initializer
3486                || node.expression !== expression
3487                || node.statement !== statement
3488                ? update(createForInStatement(initializer, expression, statement), node)
3489                : node;
3490        }
3491
3492        // @api
3493        function createForOfStatement(awaitModifier: AwaitKeyword | undefined, initializer: ForInitializer, expression: Expression, statement: Statement) {
3494            const node = createBaseNode<ForOfStatement>(SyntaxKind.ForOfStatement);
3495            node.awaitModifier = awaitModifier;
3496            node.initializer = initializer;
3497            node.expression = parenthesizerRules().parenthesizeExpressionForDisallowedComma(expression);
3498            node.statement = asEmbeddedStatement(statement);
3499            node.transformFlags |=
3500                propagateChildFlags(node.awaitModifier) |
3501                propagateChildFlags(node.initializer) |
3502                propagateChildFlags(node.expression) |
3503                propagateChildFlags(node.statement) |
3504                TransformFlags.ContainsES2015;
3505            if (awaitModifier) node.transformFlags |= TransformFlags.ContainsES2018;
3506            return node;
3507        }
3508
3509        // @api
3510        function updateForOfStatement(node: ForOfStatement, awaitModifier: AwaitKeyword | undefined, initializer: ForInitializer, expression: Expression, statement: Statement) {
3511            return node.awaitModifier !== awaitModifier
3512                || node.initializer !== initializer
3513                || node.expression !== expression
3514                || node.statement !== statement
3515                ? update(createForOfStatement(awaitModifier, initializer, expression, statement), node)
3516                : node;
3517        }
3518
3519        // @api
3520        function createContinueStatement(label?: string | Identifier): ContinueStatement {
3521            const node = createBaseNode<ContinueStatement>(SyntaxKind.ContinueStatement);
3522            node.label = asName(label);
3523            node.transformFlags |=
3524                propagateChildFlags(node.label) |
3525                TransformFlags.ContainsHoistedDeclarationOrCompletion;
3526            return node;
3527        }
3528
3529        // @api
3530        function updateContinueStatement(node: ContinueStatement, label: Identifier | undefined) {
3531            return node.label !== label
3532                ? update(createContinueStatement(label), node)
3533                : node;
3534        }
3535
3536        // @api
3537        function createBreakStatement(label?: string | Identifier): BreakStatement {
3538            const node = createBaseNode<BreakStatement>(SyntaxKind.BreakStatement);
3539            node.label = asName(label);
3540            node.transformFlags |=
3541                propagateChildFlags(node.label) |
3542                TransformFlags.ContainsHoistedDeclarationOrCompletion;
3543            return node;
3544        }
3545
3546        // @api
3547        function updateBreakStatement(node: BreakStatement, label: Identifier | undefined) {
3548            return node.label !== label
3549                ? update(createBreakStatement(label), node)
3550                : node;
3551        }
3552
3553        // @api
3554        function createReturnStatement(expression?: Expression): ReturnStatement {
3555            const node = createBaseNode<ReturnStatement>(SyntaxKind.ReturnStatement);
3556            node.expression = expression;
3557            // return in an ES2018 async generator must be awaited
3558            node.transformFlags |=
3559                propagateChildFlags(node.expression) |
3560                TransformFlags.ContainsES2018 |
3561                TransformFlags.ContainsHoistedDeclarationOrCompletion;
3562            return node;
3563        }
3564
3565        // @api
3566        function updateReturnStatement(node: ReturnStatement, expression: Expression | undefined) {
3567            return node.expression !== expression
3568                ? update(createReturnStatement(expression), node)
3569                : node;
3570        }
3571
3572        // @api
3573        function createWithStatement(expression: Expression, statement: Statement) {
3574            const node = createBaseNode<WithStatement>(SyntaxKind.WithStatement);
3575            node.expression = expression;
3576            node.statement = asEmbeddedStatement(statement);
3577            node.transformFlags |=
3578                propagateChildFlags(node.expression) |
3579                propagateChildFlags(node.statement);
3580            return node;
3581        }
3582
3583        // @api
3584        function updateWithStatement(node: WithStatement, expression: Expression, statement: Statement) {
3585            return node.expression !== expression
3586                || node.statement !== statement
3587                ? update(createWithStatement(expression, statement), node)
3588                : node;
3589        }
3590
3591        // @api
3592        function createSwitchStatement(expression: Expression, caseBlock: CaseBlock): SwitchStatement {
3593            const node = createBaseNode<SwitchStatement>(SyntaxKind.SwitchStatement);
3594            node.expression = parenthesizerRules().parenthesizeExpressionForDisallowedComma(expression);
3595            node.caseBlock = caseBlock;
3596            node.transformFlags |=
3597                propagateChildFlags(node.expression) |
3598                propagateChildFlags(node.caseBlock);
3599            return node;
3600        }
3601
3602        // @api
3603        function updateSwitchStatement(node: SwitchStatement, expression: Expression, caseBlock: CaseBlock) {
3604            return node.expression !== expression
3605                || node.caseBlock !== caseBlock
3606                ? update(createSwitchStatement(expression, caseBlock), node)
3607                : node;
3608        }
3609
3610        // @api
3611        function createLabeledStatement(label: string | Identifier, statement: Statement) {
3612            const node = createBaseNode<LabeledStatement>(SyntaxKind.LabeledStatement);
3613            node.label = asName(label);
3614            node.statement = asEmbeddedStatement(statement);
3615            node.transformFlags |=
3616                propagateChildFlags(node.label) |
3617                propagateChildFlags(node.statement);
3618            return node;
3619        }
3620
3621        // @api
3622        function updateLabeledStatement(node: LabeledStatement, label: Identifier, statement: Statement) {
3623            return node.label !== label
3624                || node.statement !== statement
3625                ? update(createLabeledStatement(label, statement), node)
3626                : node;
3627        }
3628
3629        // @api
3630        function createThrowStatement(expression: Expression) {
3631            const node = createBaseNode<ThrowStatement>(SyntaxKind.ThrowStatement);
3632            node.expression = expression;
3633            node.transformFlags |= propagateChildFlags(node.expression);
3634            return node;
3635        }
3636
3637        // @api
3638        function updateThrowStatement(node: ThrowStatement, expression: Expression) {
3639            return node.expression !== expression
3640                ? update(createThrowStatement(expression), node)
3641                : node;
3642        }
3643
3644        // @api
3645        function createTryStatement(tryBlock: Block, catchClause: CatchClause | undefined, finallyBlock: Block | undefined) {
3646            const node = createBaseNode<TryStatement>(SyntaxKind.TryStatement);
3647            node.tryBlock = tryBlock;
3648            node.catchClause = catchClause;
3649            node.finallyBlock = finallyBlock;
3650            node.transformFlags |=
3651                propagateChildFlags(node.tryBlock) |
3652                propagateChildFlags(node.catchClause) |
3653                propagateChildFlags(node.finallyBlock);
3654            return node;
3655        }
3656
3657        // @api
3658        function updateTryStatement(node: TryStatement, tryBlock: Block, catchClause: CatchClause | undefined, finallyBlock: Block | undefined) {
3659            return node.tryBlock !== tryBlock
3660                || node.catchClause !== catchClause
3661                || node.finallyBlock !== finallyBlock
3662                ? update(createTryStatement(tryBlock, catchClause, finallyBlock), node)
3663                : node;
3664        }
3665
3666        // @api
3667        function createDebuggerStatement() {
3668            return createBaseNode<DebuggerStatement>(SyntaxKind.DebuggerStatement);
3669        }
3670
3671        // @api
3672        function createVariableDeclaration(name: string | BindingName, exclamationToken: ExclamationToken | undefined, type: TypeNode | undefined, initializer: Expression | undefined) {
3673            const node = createBaseVariableLikeDeclaration<VariableDeclaration>(
3674                SyntaxKind.VariableDeclaration,
3675                /*modifiers*/ undefined,
3676                name,
3677                type,
3678                initializer && parenthesizerRules().parenthesizeExpressionForDisallowedComma(initializer)
3679            );
3680            node.exclamationToken = exclamationToken;
3681            node.transformFlags |= propagateChildFlags(node.exclamationToken);
3682            if (exclamationToken) {
3683                node.transformFlags |= TransformFlags.ContainsTypeScript;
3684            }
3685            return node;
3686        }
3687
3688        // @api
3689        function updateVariableDeclaration(node: VariableDeclaration, name: BindingName, exclamationToken: ExclamationToken | undefined, type: TypeNode | undefined, initializer: Expression | undefined) {
3690            return node.name !== name
3691                || node.type !== type
3692                || node.exclamationToken !== exclamationToken
3693                || node.initializer !== initializer
3694                ? update(createVariableDeclaration(name, exclamationToken, type, initializer), node)
3695                : node;
3696        }
3697
3698        // @api
3699        function createVariableDeclarationList(declarations: readonly VariableDeclaration[], flags = NodeFlags.None) {
3700            const node = createBaseNode<VariableDeclarationList>(SyntaxKind.VariableDeclarationList);
3701            node.flags |= flags & NodeFlags.BlockScoped;
3702            node.declarations = createNodeArray(declarations);
3703            node.transformFlags |=
3704                propagateChildrenFlags(node.declarations) |
3705                TransformFlags.ContainsHoistedDeclarationOrCompletion;
3706            if (flags & NodeFlags.BlockScoped) {
3707                node.transformFlags |=
3708                    TransformFlags.ContainsES2015 |
3709                    TransformFlags.ContainsBlockScopedBinding;
3710            }
3711            return node;
3712        }
3713
3714        // @api
3715        function updateVariableDeclarationList(node: VariableDeclarationList, declarations: readonly VariableDeclaration[]) {
3716            return node.declarations !== declarations
3717                ? update(createVariableDeclarationList(declarations, node.flags), node)
3718                : node;
3719        }
3720
3721        // @api
3722        function createFunctionDeclaration(
3723            modifiers: readonly ModifierLike[] | undefined,
3724            asteriskToken: AsteriskToken | undefined,
3725            name: string | Identifier | undefined,
3726            typeParameters: readonly TypeParameterDeclaration[] | undefined,
3727            parameters: readonly ParameterDeclaration[],
3728            type: TypeNode | undefined,
3729            body: Block | undefined
3730        ) {
3731            const node = createBaseFunctionLikeDeclaration<FunctionDeclaration>(
3732                SyntaxKind.FunctionDeclaration,
3733                modifiers,
3734                name,
3735                typeParameters,
3736                parameters,
3737                type,
3738                body
3739            );
3740            node.asteriskToken = asteriskToken;
3741            if (!node.body || modifiersToFlags(node.modifiers) & ModifierFlags.Ambient) {
3742                node.transformFlags = TransformFlags.ContainsTypeScript;
3743            }
3744            else {
3745                node.transformFlags |=
3746                    propagateChildFlags(node.asteriskToken) |
3747                    TransformFlags.ContainsHoistedDeclarationOrCompletion;
3748                if (modifiersToFlags(node.modifiers) & ModifierFlags.Async) {
3749                    if (node.asteriskToken) {
3750                        node.transformFlags |= TransformFlags.ContainsES2018;
3751                    }
3752                    else {
3753                        node.transformFlags |= TransformFlags.ContainsES2017;
3754                    }
3755                }
3756                else if (node.asteriskToken) {
3757                    node.transformFlags |= TransformFlags.ContainsGenerator;
3758                }
3759            }
3760
3761            // The following properties are used only to report grammar errors
3762            node.illegalDecorators = undefined;
3763            return node;
3764        }
3765
3766        // @api
3767        function updateFunctionDeclaration(
3768            node: FunctionDeclaration,
3769            modifiers: readonly ModifierLike[] | undefined,
3770            asteriskToken: AsteriskToken | undefined,
3771            name: Identifier | undefined,
3772            typeParameters: readonly TypeParameterDeclaration[] | undefined,
3773            parameters: readonly ParameterDeclaration[],
3774            type: TypeNode | undefined,
3775            body: Block | undefined
3776        ) {
3777            return node.modifiers !== modifiers
3778                || node.asteriskToken !== asteriskToken
3779                || node.name !== name
3780                || node.typeParameters !== typeParameters
3781                || node.parameters !== parameters
3782                || node.type !== type
3783                || node.body !== body
3784                ? finishUpdateFunctionDeclaration(createFunctionDeclaration(modifiers, asteriskToken, name, typeParameters, parameters, type, body), node)
3785                : node;
3786        }
3787
3788        function finishUpdateFunctionDeclaration(updated: Mutable<FunctionDeclaration>, original: FunctionDeclaration) {
3789            if (updated !== original) {
3790                // copy children used only for error reporting
3791                updated.illegalDecorators = original.illegalDecorators;
3792            }
3793            return finishUpdateBaseSignatureDeclaration(updated, original);
3794        }
3795
3796        // @api
3797        function createClassDeclaration(
3798            modifiers: readonly ModifierLike[] | undefined,
3799            name: string | Identifier | undefined,
3800            typeParameters: readonly TypeParameterDeclaration[] | undefined,
3801            heritageClauses: readonly HeritageClause[] | undefined,
3802            members: readonly ClassElement[]
3803        ) {
3804            const node = createBaseClassLikeDeclaration<ClassDeclaration>(
3805                SyntaxKind.ClassDeclaration,
3806                modifiers,
3807                name,
3808                typeParameters,
3809                heritageClauses,
3810                members
3811            );
3812            if (modifiersToFlags(node.modifiers) & ModifierFlags.Ambient) {
3813                node.transformFlags = TransformFlags.ContainsTypeScript;
3814            }
3815            else {
3816                node.transformFlags |= TransformFlags.ContainsES2015;
3817                if (node.transformFlags & TransformFlags.ContainsTypeScriptClassSyntax) {
3818                    node.transformFlags |= TransformFlags.ContainsTypeScript;
3819                }
3820            }
3821            return node;
3822        }
3823
3824        // @api
3825        function updateClassDeclaration(
3826            node: ClassDeclaration,
3827            modifiers: readonly ModifierLike[] | undefined,
3828            name: Identifier | undefined,
3829            typeParameters: readonly TypeParameterDeclaration[] | undefined,
3830            heritageClauses: readonly HeritageClause[] | undefined,
3831            members: readonly ClassElement[]
3832        ) {
3833            return node.modifiers !== modifiers
3834                || node.name !== name
3835                || node.typeParameters !== typeParameters
3836                || node.heritageClauses !== heritageClauses
3837                || node.members !== members
3838                ? update(createClassDeclaration(modifiers, name, typeParameters, heritageClauses, members), node)
3839                : node;
3840        }
3841
3842        // @api
3843        function createStructDeclaration(
3844            modifiers: readonly Modifier[] | undefined,
3845            name: string | Identifier | undefined,
3846            typeParameters: readonly TypeParameterDeclaration[] | undefined,
3847            heritageClauses: readonly HeritageClause[] | undefined,
3848            members: readonly ClassElement[]
3849        ) {
3850            const node = createBaseClassLikeDeclaration<StructDeclaration>(
3851                SyntaxKind.StructDeclaration,
3852                modifiers,
3853                name,
3854                typeParameters,
3855                heritageClauses,
3856                members
3857            );
3858            if (modifiersToFlags(node.modifiers) & ModifierFlags.Ambient) {
3859                node.transformFlags = TransformFlags.ContainsTypeScript;
3860            }
3861            else {
3862                node.transformFlags |= TransformFlags.ContainsES2015;
3863                if (node.transformFlags & TransformFlags.ContainsTypeScriptClassSyntax) {
3864                    node.transformFlags |= TransformFlags.ContainsTypeScript;
3865                }
3866            }
3867            return node;
3868        }
3869
3870        // @api
3871        function updateStructDeclaration(
3872            node: StructDeclaration,
3873            modifiers: readonly Modifier[] | undefined,
3874            name: Identifier | undefined,
3875            typeParameters: readonly TypeParameterDeclaration[] | undefined,
3876            heritageClauses: readonly HeritageClause[] | undefined,
3877            members: readonly ClassElement[]
3878        ) {
3879            return node.modifiers !== modifiers
3880                || node.name !== name
3881                || node.typeParameters !== typeParameters
3882                || node.heritageClauses !== heritageClauses
3883                || node.members !== members
3884                ? update(createStructDeclaration(modifiers, name, typeParameters, heritageClauses, members), node)
3885                : node;
3886        }
3887
3888        // @api
3889        function createInterfaceDeclaration(
3890            modifiers: readonly Modifier[] | undefined,
3891            name: string | Identifier,
3892            typeParameters: readonly TypeParameterDeclaration[] | undefined,
3893            heritageClauses: readonly HeritageClause[] | undefined,
3894            members: readonly TypeElement[]
3895        ) {
3896            const node = createBaseInterfaceOrClassLikeDeclaration<InterfaceDeclaration>(
3897                SyntaxKind.InterfaceDeclaration,
3898                modifiers,
3899                name,
3900                typeParameters,
3901                heritageClauses
3902            );
3903            node.members = createNodeArray(members);
3904            node.transformFlags = TransformFlags.ContainsTypeScript;
3905
3906            // The following properties are used only to report grammar errors
3907            node.illegalDecorators = undefined;
3908            return node;
3909        }
3910
3911        // @api
3912        function updateInterfaceDeclaration(
3913            node: InterfaceDeclaration,
3914            modifiers: readonly Modifier[] | undefined,
3915            name: Identifier,
3916            typeParameters: readonly TypeParameterDeclaration[] | undefined,
3917            heritageClauses: readonly HeritageClause[] | undefined,
3918            members: readonly TypeElement[]
3919        ) {
3920            return node.modifiers !== modifiers
3921                || node.name !== name
3922                || node.typeParameters !== typeParameters
3923                || node.heritageClauses !== heritageClauses
3924                || node.members !== members
3925                ? finishUpdateInterfaceDeclaration(createInterfaceDeclaration(modifiers, name, typeParameters, heritageClauses, members), node)
3926                : node;
3927        }
3928
3929        function finishUpdateInterfaceDeclaration(updated: Mutable<InterfaceDeclaration>, original: InterfaceDeclaration) {
3930            if (updated !== original) {
3931                updated.illegalDecorators = original.illegalDecorators;
3932            }
3933            return update(updated, original);
3934        }
3935
3936        // @api
3937        function createTypeAliasDeclaration(
3938            modifiers: readonly Modifier[] | undefined,
3939            name: string | Identifier,
3940            typeParameters: readonly TypeParameterDeclaration[] | undefined,
3941            type: TypeNode
3942        ) {
3943            const node = createBaseGenericNamedDeclaration<TypeAliasDeclaration>(
3944                SyntaxKind.TypeAliasDeclaration,
3945                modifiers,
3946                name,
3947                typeParameters
3948            );
3949            node.type = type;
3950            node.transformFlags = TransformFlags.ContainsTypeScript;
3951
3952            // The following properties are used only to report grammar errors
3953            node.illegalDecorators = undefined;
3954            return node;
3955        }
3956
3957        // @api
3958        function updateTypeAliasDeclaration(
3959            node: TypeAliasDeclaration,
3960            modifiers: readonly Modifier[] | undefined,
3961            name: Identifier,
3962            typeParameters: readonly TypeParameterDeclaration[] | undefined,
3963            type: TypeNode
3964        ) {
3965            return node.modifiers !== modifiers
3966                || node.name !== name
3967                || node.typeParameters !== typeParameters
3968                || node.type !== type
3969                ? finishUpdateTypeAliasDeclaration(createTypeAliasDeclaration(modifiers, name, typeParameters, type), node)
3970                : node;
3971        }
3972
3973        function finishUpdateTypeAliasDeclaration(updated: Mutable<TypeAliasDeclaration>, original: TypeAliasDeclaration) {
3974            if (updated !== original) {
3975                updated.illegalDecorators = original.illegalDecorators;
3976            }
3977            return update(updated, original);
3978        }
3979
3980        // @api
3981        function createEnumDeclaration(
3982            modifiers: readonly Modifier[] | undefined,
3983            name: string | Identifier,
3984            members: readonly EnumMember[]
3985        ) {
3986            const node = createBaseNamedDeclaration<EnumDeclaration>(
3987                SyntaxKind.EnumDeclaration,
3988                modifiers,
3989                name
3990            );
3991            node.members = createNodeArray(members);
3992            node.transformFlags |=
3993                propagateChildrenFlags(node.members) |
3994                TransformFlags.ContainsTypeScript;
3995            node.transformFlags &= ~TransformFlags.ContainsPossibleTopLevelAwait; // Enum declarations cannot contain `await`
3996
3997            // The following properties are used only to report grammar errors
3998            node.illegalDecorators = undefined;
3999            return node;
4000        }
4001
4002        // @api
4003        function updateEnumDeclaration(
4004            node: EnumDeclaration,
4005            modifiers: readonly Modifier[] | undefined,
4006            name: Identifier,
4007            members: readonly EnumMember[]) {
4008            return node.modifiers !== modifiers
4009                || node.name !== name
4010                || node.members !== members
4011                ? finishUpdateEnumDeclaration(createEnumDeclaration(modifiers, name, members), node)
4012                : node;
4013        }
4014
4015        function finishUpdateEnumDeclaration(updated: Mutable<EnumDeclaration>, original: EnumDeclaration) {
4016            if (updated !== original) {
4017                updated.illegalDecorators = original.illegalDecorators;
4018            }
4019            return update(updated, original);
4020        }
4021
4022        // @api
4023        function createModuleDeclaration(
4024            modifiers: readonly Modifier[] | undefined,
4025            name: ModuleName,
4026            body: ModuleBody | undefined,
4027            flags = NodeFlags.None
4028        ) {
4029            const node = createBaseDeclaration<ModuleDeclaration>(SyntaxKind.ModuleDeclaration);
4030            node.modifiers = asNodeArray(modifiers);
4031            node.flags |= flags & (NodeFlags.Namespace | NodeFlags.NestedNamespace | NodeFlags.GlobalAugmentation);
4032            node.name = name;
4033            node.body = body;
4034            if (modifiersToFlags(node.modifiers) & ModifierFlags.Ambient) {
4035                node.transformFlags = TransformFlags.ContainsTypeScript;
4036            }
4037            else {
4038                node.transformFlags |=
4039                    propagateChildrenFlags(node.modifiers) |
4040                    propagateChildFlags(node.name) |
4041                    propagateChildFlags(node.body) |
4042                    TransformFlags.ContainsTypeScript;
4043            }
4044            node.transformFlags &= ~TransformFlags.ContainsPossibleTopLevelAwait; // Module declarations cannot contain `await`.
4045
4046            // The following properties are used only to report grammar errors
4047            node.illegalDecorators = undefined;
4048            return node;
4049        }
4050
4051        // @api
4052        function updateModuleDeclaration(
4053            node: ModuleDeclaration,
4054            modifiers: readonly Modifier[] | undefined,
4055            name: ModuleName,
4056            body: ModuleBody | undefined
4057        ) {
4058            return node.modifiers !== modifiers
4059                || node.name !== name
4060                || node.body !== body
4061                ? finishUpdateModuleDeclaration(createModuleDeclaration(modifiers, name, body, node.flags), node)
4062                : node;
4063        }
4064
4065        function finishUpdateModuleDeclaration(updated: Mutable<ModuleDeclaration>, original: ModuleDeclaration) {
4066            if (updated !== original) {
4067                updated.illegalDecorators = original.illegalDecorators;
4068            }
4069            return update(updated, original);
4070        }
4071
4072        // @api
4073        function createModuleBlock(statements: readonly Statement[]) {
4074            const node = createBaseNode<ModuleBlock>(SyntaxKind.ModuleBlock);
4075            node.statements = createNodeArray(statements);
4076            node.transformFlags |= propagateChildrenFlags(node.statements);
4077            return node;
4078        }
4079
4080        // @api
4081        function updateModuleBlock(node: ModuleBlock, statements: readonly Statement[]) {
4082            return node.statements !== statements
4083                ? update(createModuleBlock(statements), node)
4084                : node;
4085        }
4086
4087        // @api
4088        function createCaseBlock(clauses: readonly CaseOrDefaultClause[]): CaseBlock {
4089            const node = createBaseNode<CaseBlock>(SyntaxKind.CaseBlock);
4090            node.clauses = createNodeArray(clauses);
4091            node.transformFlags |= propagateChildrenFlags(node.clauses);
4092            return node;
4093        }
4094
4095        // @api
4096        function updateCaseBlock(node: CaseBlock, clauses: readonly CaseOrDefaultClause[]) {
4097            return node.clauses !== clauses
4098                ? update(createCaseBlock(clauses), node)
4099                : node;
4100        }
4101
4102        // @api
4103        function createNamespaceExportDeclaration(name: string | Identifier) {
4104            const node = createBaseNamedDeclaration<NamespaceExportDeclaration>(
4105                SyntaxKind.NamespaceExportDeclaration,
4106                /*modifiers*/ undefined,
4107                name
4108            );
4109            node.transformFlags = TransformFlags.ContainsTypeScript;
4110
4111            // The following properties are used only to report grammar errors
4112            node.illegalDecorators = undefined;
4113            node.modifiers = undefined;
4114            return node;
4115        }
4116
4117        // @api
4118        function updateNamespaceExportDeclaration(node: NamespaceExportDeclaration, name: Identifier) {
4119            return node.name !== name
4120                ? finishUpdateNamespaceExportDeclaration(createNamespaceExportDeclaration(name), node)
4121                : node;
4122        }
4123
4124        function finishUpdateNamespaceExportDeclaration(updated: Mutable<NamespaceExportDeclaration>, original: NamespaceExportDeclaration) {
4125            if (updated !== original) {
4126                updated.illegalDecorators = original.illegalDecorators;
4127                updated.modifiers = original.modifiers;
4128            }
4129            return update(updated, original);
4130        }
4131
4132        // @api
4133        function createImportEqualsDeclaration(
4134            modifiers: readonly Modifier[] | undefined,
4135            isTypeOnly: boolean,
4136            name: string | Identifier,
4137            moduleReference: ModuleReference
4138        ) {
4139            const node = createBaseNamedDeclaration<ImportEqualsDeclaration>(
4140                SyntaxKind.ImportEqualsDeclaration,
4141                modifiers,
4142                name
4143            );
4144            node.isTypeOnly = isTypeOnly;
4145            node.moduleReference = moduleReference;
4146            node.transformFlags |= propagateChildFlags(node.moduleReference);
4147            if (!isExternalModuleReference(node.moduleReference)) node.transformFlags |= TransformFlags.ContainsTypeScript;
4148            node.transformFlags &= ~TransformFlags.ContainsPossibleTopLevelAwait; // Import= declaration is always parsed in an Await context
4149
4150            // The following properties are used only to report grammar errors
4151            node.illegalDecorators = undefined;
4152            return node;
4153        }
4154
4155        // @api
4156        function updateImportEqualsDeclaration(
4157            node: ImportEqualsDeclaration,
4158            modifiers: readonly Modifier[] | undefined,
4159            isTypeOnly: boolean,
4160            name: Identifier,
4161            moduleReference: ModuleReference
4162        ) {
4163            return node.modifiers !== modifiers
4164                || node.isTypeOnly !== isTypeOnly
4165                || node.name !== name
4166                || node.moduleReference !== moduleReference
4167                ? finishUpdateImportEqualsDeclaration(createImportEqualsDeclaration(modifiers, isTypeOnly, name, moduleReference), node)
4168                : node;
4169        }
4170
4171        function finishUpdateImportEqualsDeclaration(updated: Mutable<ImportEqualsDeclaration>, original: ImportEqualsDeclaration) {
4172            if (updated !== original) {
4173                updated.illegalDecorators = original.illegalDecorators;
4174            }
4175            return update(updated, original);
4176        }
4177
4178        // @api
4179        function createImportDeclaration(
4180            modifiers: readonly Modifier[] | undefined,
4181            importClause: ImportClause | undefined,
4182            moduleSpecifier: Expression,
4183            assertClause: AssertClause | undefined
4184        ): ImportDeclaration {
4185            const node = createBaseDeclaration<ImportDeclaration>(SyntaxKind.ImportDeclaration);
4186            node.modifiers = asNodeArray(modifiers);
4187            node.importClause = importClause;
4188            node.moduleSpecifier = moduleSpecifier;
4189            node.assertClause = assertClause;
4190            node.transformFlags |=
4191                propagateChildFlags(node.importClause) |
4192                propagateChildFlags(node.moduleSpecifier);
4193            node.transformFlags &= ~TransformFlags.ContainsPossibleTopLevelAwait; // always parsed in an Await context
4194
4195            // The following properties are used only to report grammar errors
4196            node.illegalDecorators = undefined;
4197            return node;
4198        }
4199
4200        // @api
4201        function updateImportDeclaration(
4202            node: ImportDeclaration,
4203            modifiers: readonly Modifier[] | undefined,
4204            importClause: ImportClause | undefined,
4205            moduleSpecifier: Expression,
4206            assertClause: AssertClause | undefined
4207        ) {
4208            return node.modifiers !== modifiers
4209                || node.importClause !== importClause
4210                || node.moduleSpecifier !== moduleSpecifier
4211                || node.assertClause !== assertClause
4212                ? finishUpdateImportDeclaration(createImportDeclaration(modifiers, importClause, moduleSpecifier, assertClause), node)
4213                : node;
4214        }
4215
4216        function finishUpdateImportDeclaration(updated: Mutable<ImportDeclaration>, original: ImportDeclaration) {
4217            if (updated !== original) {
4218                updated.illegalDecorators = original.illegalDecorators;
4219            }
4220            return update(updated, original);
4221        }
4222
4223        // @api
4224        function createImportClause(isTypeOnly: boolean, name: Identifier | undefined, namedBindings: NamedImportBindings | undefined): ImportClause {
4225            const node = createBaseNode<ImportClause>(SyntaxKind.ImportClause);
4226            node.isTypeOnly = isTypeOnly;
4227            node.name = name;
4228            node.namedBindings = namedBindings;
4229            node.transformFlags |=
4230                propagateChildFlags(node.name) |
4231                propagateChildFlags(node.namedBindings);
4232            if (isTypeOnly) {
4233                node.transformFlags |= TransformFlags.ContainsTypeScript;
4234            }
4235            node.transformFlags &= ~TransformFlags.ContainsPossibleTopLevelAwait; // always parsed in an Await context
4236
4237            node.isLazy = undefined;
4238            return node;
4239        }
4240
4241        // @api
4242        function updateImportClause(node: ImportClause, isTypeOnly: boolean, name: Identifier | undefined, namedBindings: NamedImportBindings | undefined) {
4243            return node.isTypeOnly !== isTypeOnly
4244                || node.name !== name
4245                || node.namedBindings !== namedBindings
4246                ? finishUpdateImportClause(createImportClause(isTypeOnly, name, namedBindings), node)
4247                : node;
4248        }
4249
4250        function finishUpdateImportClause(updated: Mutable<ImportClause>, original: ImportClause) {
4251            if (updated !== original) {
4252                updated.isLazy = original.isLazy;
4253            }
4254            return update(updated, original);
4255        }
4256
4257        // @api
4258        function createAssertClause(elements: readonly AssertEntry[], multiLine?: boolean): AssertClause {
4259            const node = createBaseNode<AssertClause>(SyntaxKind.AssertClause);
4260            node.elements = createNodeArray(elements);
4261            node.multiLine = multiLine;
4262            node.transformFlags |= TransformFlags.ContainsESNext;
4263            return node;
4264        }
4265
4266        // @api
4267        function updateAssertClause(node: AssertClause, elements: readonly AssertEntry[], multiLine?: boolean): AssertClause {
4268            return node.elements !== elements
4269                || node.multiLine !== multiLine
4270                ? update(createAssertClause(elements, multiLine), node)
4271                : node;
4272        }
4273
4274        // @api
4275        function createAssertEntry(name: AssertionKey, value: Expression): AssertEntry {
4276            const node = createBaseNode<AssertEntry>(SyntaxKind.AssertEntry);
4277            node.name = name;
4278            node.value = value;
4279            node.transformFlags |= TransformFlags.ContainsESNext;
4280            return node;
4281        }
4282
4283        // @api
4284        function updateAssertEntry(node: AssertEntry, name: AssertionKey, value: Expression): AssertEntry {
4285            return node.name !== name
4286                || node.value !== value
4287                ? update(createAssertEntry(name, value), node)
4288                : node;
4289        }
4290
4291        // @api
4292        function createImportTypeAssertionContainer(clause: AssertClause, multiLine?: boolean): ImportTypeAssertionContainer {
4293            const node = createBaseNode<ImportTypeAssertionContainer>(SyntaxKind.ImportTypeAssertionContainer);
4294            node.assertClause = clause;
4295            node.multiLine = multiLine;
4296            return node;
4297        }
4298
4299        // @api
4300        function updateImportTypeAssertionContainer(node: ImportTypeAssertionContainer, clause: AssertClause, multiLine?: boolean): ImportTypeAssertionContainer {
4301            return node.assertClause !== clause
4302                || node.multiLine !== multiLine
4303                ? update(createImportTypeAssertionContainer(clause, multiLine), node)
4304                : node;
4305        }
4306
4307        // @api
4308        function createNamespaceImport(name: Identifier): NamespaceImport {
4309            const node = createBaseNode<NamespaceImport>(SyntaxKind.NamespaceImport);
4310            node.name = name;
4311            node.transformFlags |= propagateChildFlags(node.name);
4312            node.transformFlags &= ~TransformFlags.ContainsPossibleTopLevelAwait; // always parsed in an Await context
4313            return node;
4314        }
4315
4316        // @api
4317        function updateNamespaceImport(node: NamespaceImport, name: Identifier) {
4318            return node.name !== name
4319                ? update(createNamespaceImport(name), node)
4320                : node;
4321        }
4322
4323        // @api
4324        function createNamespaceExport(name: Identifier): NamespaceExport {
4325            const node = createBaseNode<NamespaceExport>(SyntaxKind.NamespaceExport);
4326            node.name = name;
4327            node.transformFlags |=
4328                propagateChildFlags(node.name) |
4329                TransformFlags.ContainsESNext;
4330            node.transformFlags &= ~TransformFlags.ContainsPossibleTopLevelAwait; // always parsed in an Await context
4331            return node;
4332        }
4333
4334        // @api
4335        function updateNamespaceExport(node: NamespaceExport, name: Identifier) {
4336            return node.name !== name
4337                ? update(createNamespaceExport(name), node)
4338                : node;
4339        }
4340
4341        // @api
4342        function createNamedImports(elements: readonly ImportSpecifier[]): NamedImports {
4343            const node = createBaseNode<NamedImports>(SyntaxKind.NamedImports);
4344            node.elements = createNodeArray(elements);
4345            node.transformFlags |= propagateChildrenFlags(node.elements);
4346            node.transformFlags &= ~TransformFlags.ContainsPossibleTopLevelAwait; // always parsed in an Await context
4347            return node;
4348        }
4349
4350        // @api
4351        function updateNamedImports(node: NamedImports, elements: readonly ImportSpecifier[]) {
4352            return node.elements !== elements
4353                ? update(createNamedImports(elements), node)
4354                : node;
4355        }
4356
4357        // @api
4358        function createImportSpecifier(isTypeOnly: boolean, propertyName: Identifier | undefined, name: Identifier) {
4359            const node = createBaseNode<ImportSpecifier>(SyntaxKind.ImportSpecifier);
4360            node.isTypeOnly = isTypeOnly;
4361            node.propertyName = propertyName;
4362            node.name = name;
4363            node.transformFlags |=
4364                propagateChildFlags(node.propertyName) |
4365                propagateChildFlags(node.name);
4366            node.transformFlags &= ~TransformFlags.ContainsPossibleTopLevelAwait; // always parsed in an Await context
4367            return node;
4368        }
4369
4370        // @api
4371        function updateImportSpecifier(node: ImportSpecifier, isTypeOnly: boolean, propertyName: Identifier | undefined, name: Identifier) {
4372            return node.isTypeOnly !== isTypeOnly
4373                || node.propertyName !== propertyName
4374                || node.name !== name
4375                ? update(createImportSpecifier(isTypeOnly, propertyName, name), node)
4376                : node;
4377        }
4378
4379        // @api
4380        function createExportAssignment(
4381            modifiers: readonly Modifier[] | undefined,
4382            isExportEquals: boolean | undefined,
4383            expression: Expression
4384        ) {
4385            const node = createBaseDeclaration<ExportAssignment>(SyntaxKind.ExportAssignment);
4386            node.modifiers = asNodeArray(modifiers);
4387            node.isExportEquals = isExportEquals;
4388            node.expression = isExportEquals
4389                ? parenthesizerRules().parenthesizeRightSideOfBinary(SyntaxKind.EqualsToken, /*leftSide*/ undefined, expression)
4390                : parenthesizerRules().parenthesizeExpressionOfExportDefault(expression);
4391            node.transformFlags |= propagateChildrenFlags(node.modifiers) | propagateChildFlags(node.expression);
4392            node.transformFlags &= ~TransformFlags.ContainsPossibleTopLevelAwait; // always parsed in an Await context
4393
4394            // The following properties are used only to report grammar errors
4395            node.illegalDecorators = undefined;
4396            return node;
4397        }
4398
4399        // @api
4400        function updateExportAssignment(
4401            node: ExportAssignment,
4402            modifiers: readonly Modifier[] | undefined,
4403            expression: Expression
4404        ) {
4405            return node.modifiers !== modifiers
4406                || node.expression !== expression
4407                ? finishUpdateExportAssignment(createExportAssignment(modifiers, node.isExportEquals, expression), node)
4408                : node;
4409        }
4410
4411        function finishUpdateExportAssignment(updated: Mutable<ExportAssignment>, original: ExportAssignment) {
4412            if (updated !== original) {
4413                updated.illegalDecorators = original.illegalDecorators;
4414            }
4415            return update(updated, original);
4416        }
4417
4418        // @api
4419        function createExportDeclaration(
4420            modifiers: readonly Modifier[] | undefined,
4421            isTypeOnly: boolean,
4422            exportClause: NamedExportBindings | undefined,
4423            moduleSpecifier?: Expression,
4424            assertClause?: AssertClause
4425        ) {
4426            const node = createBaseDeclaration<ExportDeclaration>(SyntaxKind.ExportDeclaration);
4427            node.modifiers = asNodeArray(modifiers);
4428            node.isTypeOnly = isTypeOnly;
4429            node.exportClause = exportClause;
4430            node.moduleSpecifier = moduleSpecifier;
4431            node.assertClause = assertClause;
4432            node.transformFlags |=
4433                propagateChildrenFlags(node.modifiers) |
4434                propagateChildFlags(node.exportClause) |
4435                propagateChildFlags(node.moduleSpecifier);
4436            node.transformFlags &= ~TransformFlags.ContainsPossibleTopLevelAwait; // always parsed in an Await context
4437
4438            // The following properties are used only to report grammar errors
4439            node.illegalDecorators = undefined;
4440            return node;
4441        }
4442
4443        // @api
4444        function updateExportDeclaration(
4445            node: ExportDeclaration,
4446            modifiers: readonly Modifier[] | undefined,
4447            isTypeOnly: boolean,
4448            exportClause: NamedExportBindings | undefined,
4449            moduleSpecifier: Expression | undefined,
4450            assertClause: AssertClause | undefined
4451        ) {
4452            return node.modifiers !== modifiers
4453                || node.isTypeOnly !== isTypeOnly
4454                || node.exportClause !== exportClause
4455                || node.moduleSpecifier !== moduleSpecifier
4456                || node.assertClause !== assertClause
4457                ? finishUpdateExportDeclaration(createExportDeclaration(modifiers, isTypeOnly, exportClause, moduleSpecifier, assertClause), node)
4458                : node;
4459        }
4460
4461        function finishUpdateExportDeclaration(updated: Mutable<ExportDeclaration>, original: ExportDeclaration) {
4462            if (updated !== original) {
4463                updated.illegalDecorators = original.illegalDecorators;
4464            }
4465            return update(updated, original);
4466        }
4467
4468        // @api
4469        function createNamedExports(elements: readonly ExportSpecifier[]) {
4470            const node = createBaseNode<NamedExports>(SyntaxKind.NamedExports);
4471            node.elements = createNodeArray(elements);
4472            node.transformFlags |= propagateChildrenFlags(node.elements);
4473            node.transformFlags &= ~TransformFlags.ContainsPossibleTopLevelAwait; // always parsed in an Await context
4474            return node;
4475        }
4476
4477        // @api
4478        function updateNamedExports(node: NamedExports, elements: readonly ExportSpecifier[]) {
4479            return node.elements !== elements
4480                ? update(createNamedExports(elements), node)
4481                : node;
4482        }
4483
4484        // @api
4485        function createExportSpecifier(isTypeOnly: boolean, propertyName: string | Identifier | undefined, name: string | Identifier) {
4486            const node = createBaseNode<ExportSpecifier>(SyntaxKind.ExportSpecifier);
4487            node.isTypeOnly = isTypeOnly;
4488            node.propertyName = asName(propertyName);
4489            node.name = asName(name);
4490            node.transformFlags |=
4491                propagateChildFlags(node.propertyName) |
4492                propagateChildFlags(node.name);
4493            node.transformFlags &= ~TransformFlags.ContainsPossibleTopLevelAwait; // always parsed in an Await context
4494            return node;
4495        }
4496
4497        // @api
4498        function updateExportSpecifier(node: ExportSpecifier, isTypeOnly: boolean, propertyName: Identifier | undefined, name: Identifier) {
4499            return node.isTypeOnly !== isTypeOnly
4500                || node.propertyName !== propertyName
4501                || node.name !== name
4502                ? update(createExportSpecifier(isTypeOnly, propertyName, name), node)
4503                : node;
4504        }
4505
4506        // @api
4507        function createMissingDeclaration(): MissingDeclaration {
4508            const node = createBaseDeclaration<MissingDeclaration>(SyntaxKind.MissingDeclaration);
4509            return node;
4510        }
4511
4512        //
4513        // Module references
4514        //
4515
4516        // @api
4517        function createExternalModuleReference(expression: Expression) {
4518            const node = createBaseNode<ExternalModuleReference>(SyntaxKind.ExternalModuleReference);
4519            node.expression = expression;
4520            node.transformFlags |= propagateChildFlags(node.expression);
4521            node.transformFlags &= ~TransformFlags.ContainsPossibleTopLevelAwait; // always parsed in an Await context
4522            return node;
4523        }
4524
4525        // @api
4526        function updateExternalModuleReference(node: ExternalModuleReference, expression: Expression) {
4527            return node.expression !== expression
4528                ? update(createExternalModuleReference(expression), node)
4529                : node;
4530        }
4531
4532        //
4533        // JSDoc
4534        //
4535
4536        // @api
4537        // createJSDocAllType
4538        // createJSDocUnknownType
4539        function createJSDocPrimaryTypeWorker<T extends JSDocType>(kind: T["kind"]) {
4540            return createBaseNode(kind);
4541        }
4542
4543        // @api
4544        // createJSDocNullableType
4545        // createJSDocNonNullableType
4546        function createJSDocPrePostfixUnaryTypeWorker<T extends JSDocType & { readonly type: TypeNode | undefined; readonly postfix: boolean }>(kind: T["kind"], type: T["type"], postfix = false): T {
4547            const node = createJSDocUnaryTypeWorker(
4548                kind,
4549                postfix ? type && parenthesizerRules().parenthesizeNonArrayTypeOfPostfixType(type) : type
4550            ) as Mutable<T>;
4551            node.postfix = postfix;
4552            return node;
4553        }
4554
4555        // @api
4556        // createJSDocOptionalType
4557        // createJSDocVariadicType
4558        // createJSDocNamepathType
4559        function createJSDocUnaryTypeWorker<T extends JSDocType & { readonly type: TypeNode | undefined; }>(kind: T["kind"], type: T["type"]): T {
4560            const node = createBaseNode<T>(kind);
4561            node.type = type;
4562            return node;
4563        }
4564
4565        // @api
4566        // updateJSDocNonNullableType
4567        // updateJSDocNullableType
4568        function updateJSDocPrePostfixUnaryTypeWorker<T extends JSDocType & { readonly type: TypeNode | undefined; readonly postfix: boolean; }>(kind: T["kind"], node: T, type: T["type"]): T {
4569            return node.type !== type
4570            ? update(createJSDocPrePostfixUnaryTypeWorker(kind, type, node.postfix), node)
4571            : node;
4572        }
4573
4574        // @api
4575        // updateJSDocOptionalType
4576        // updateJSDocVariadicType
4577        // updateJSDocNamepathType
4578        function updateJSDocUnaryTypeWorker<T extends JSDocType & { readonly type: TypeNode | undefined; }>(kind: T["kind"], node: T, type: T["type"]): T {
4579            return node.type !== type
4580                ? update(createJSDocUnaryTypeWorker(kind, type), node)
4581                : node;
4582        }
4583
4584        // @api
4585        function createJSDocFunctionType(parameters: readonly ParameterDeclaration[], type: TypeNode | undefined): JSDocFunctionType {
4586            const node = createBaseSignatureDeclaration<JSDocFunctionType>(
4587                SyntaxKind.JSDocFunctionType,
4588                /*modifiers*/ undefined,
4589                /*name*/ undefined,
4590                /*typeParameters*/ undefined,
4591                parameters,
4592                type
4593            );
4594            return node;
4595        }
4596
4597        // @api
4598        function updateJSDocFunctionType(node: JSDocFunctionType, parameters: readonly ParameterDeclaration[], type: TypeNode | undefined): JSDocFunctionType {
4599            return node.parameters !== parameters
4600                || node.type !== type
4601                ? update(createJSDocFunctionType(parameters, type), node)
4602                : node;
4603        }
4604
4605        // @api
4606        function createJSDocTypeLiteral(propertyTags?: readonly JSDocPropertyLikeTag[], isArrayType = false): JSDocTypeLiteral {
4607            const node = createBaseNode<JSDocTypeLiteral>(SyntaxKind.JSDocTypeLiteral);
4608            node.jsDocPropertyTags = asNodeArray(propertyTags);
4609            node.isArrayType = isArrayType;
4610            return node;
4611        }
4612
4613        // @api
4614        function updateJSDocTypeLiteral(node: JSDocTypeLiteral, propertyTags: readonly JSDocPropertyLikeTag[] | undefined, isArrayType: boolean): JSDocTypeLiteral {
4615            return node.jsDocPropertyTags !== propertyTags
4616                || node.isArrayType !== isArrayType
4617                ? update(createJSDocTypeLiteral(propertyTags, isArrayType), node)
4618                : node;
4619        }
4620
4621        // @api
4622        function createJSDocTypeExpression(type: TypeNode): JSDocTypeExpression {
4623            const node = createBaseNode<JSDocTypeExpression>(SyntaxKind.JSDocTypeExpression);
4624            node.type = type;
4625            return node;
4626        }
4627
4628        // @api
4629        function updateJSDocTypeExpression(node: JSDocTypeExpression, type: TypeNode): JSDocTypeExpression {
4630            return node.type !== type
4631                ? update(createJSDocTypeExpression(type), node)
4632                : node;
4633        }
4634
4635        // @api
4636        function createJSDocSignature(typeParameters: readonly JSDocTemplateTag[] | undefined, parameters: readonly JSDocParameterTag[], type?: JSDocReturnTag): JSDocSignature {
4637            const node = createBaseNode<JSDocSignature>(SyntaxKind.JSDocSignature);
4638            node.typeParameters = asNodeArray(typeParameters);
4639            node.parameters = createNodeArray(parameters);
4640            node.type = type;
4641            return node;
4642        }
4643
4644        // @api
4645        function updateJSDocSignature(node: JSDocSignature, typeParameters: readonly JSDocTemplateTag[] | undefined, parameters: readonly JSDocParameterTag[], type: JSDocReturnTag | undefined): JSDocSignature {
4646            return node.typeParameters !== typeParameters
4647                || node.parameters !== parameters
4648                || node.type !== type
4649                ? update(createJSDocSignature(typeParameters, parameters, type), node)
4650                : node;
4651        }
4652
4653        function getDefaultTagName(node: JSDocTag) {
4654            const defaultTagName = getDefaultTagNameForKind(node.kind);
4655            return node.tagName.escapedText === escapeLeadingUnderscores(defaultTagName)
4656                ? node.tagName
4657                : createIdentifier(defaultTagName);
4658        }
4659
4660        // @api
4661        function createBaseJSDocTag<T extends JSDocTag>(kind: T["kind"], tagName: Identifier, comment: string | NodeArray<JSDocComment> | undefined) {
4662            const node = createBaseNode<T>(kind);
4663            node.tagName = tagName;
4664            node.comment = comment;
4665            return node;
4666        }
4667
4668        // @api
4669        function createJSDocTemplateTag(tagName: Identifier | undefined, constraint: JSDocTypeExpression | undefined, typeParameters: readonly TypeParameterDeclaration[], comment?: string | NodeArray<JSDocComment>): JSDocTemplateTag {
4670            const node = createBaseJSDocTag<JSDocTemplateTag>(SyntaxKind.JSDocTemplateTag, tagName ?? createIdentifier("template"), comment);
4671            node.constraint = constraint;
4672            node.typeParameters = createNodeArray(typeParameters);
4673            return node;
4674        }
4675
4676        // @api
4677        function updateJSDocTemplateTag(node: JSDocTemplateTag, tagName: Identifier = getDefaultTagName(node), constraint: JSDocTypeExpression | undefined, typeParameters: readonly TypeParameterDeclaration[], comment: string | NodeArray<JSDocComment> | undefined): JSDocTemplateTag {
4678            return node.tagName !== tagName
4679                || node.constraint !== constraint
4680                || node.typeParameters !== typeParameters
4681                || node.comment !== comment
4682                ? update(createJSDocTemplateTag(tagName, constraint, typeParameters, comment), node)
4683                : node;
4684        }
4685
4686        // @api
4687        function createJSDocTypedefTag(tagName: Identifier | undefined, typeExpression?: JSDocTypeExpression, fullName?: Identifier | JSDocNamespaceDeclaration, comment?: string | NodeArray<JSDocComment>): JSDocTypedefTag {
4688            const node = createBaseJSDocTag<JSDocTypedefTag>(SyntaxKind.JSDocTypedefTag, tagName ?? createIdentifier("typedef"), comment);
4689            node.typeExpression = typeExpression;
4690            node.fullName = fullName;
4691            node.name = getJSDocTypeAliasName(fullName);
4692            return node;
4693        }
4694
4695        // @api
4696        function updateJSDocTypedefTag(node: JSDocTypedefTag, tagName: Identifier = getDefaultTagName(node), typeExpression: JSDocTypeExpression | undefined, fullName: Identifier | JSDocNamespaceDeclaration | undefined, comment: string | NodeArray<JSDocComment> | undefined): JSDocTypedefTag {
4697            return node.tagName !== tagName
4698                || node.typeExpression !== typeExpression
4699                || node.fullName !== fullName
4700                || node.comment !== comment
4701                ? update(createJSDocTypedefTag(tagName, typeExpression, fullName, comment), node)
4702                : node;
4703        }
4704
4705        // @api
4706        function createJSDocParameterTag(tagName: Identifier | undefined, name: EntityName, isBracketed: boolean, typeExpression?: JSDocTypeExpression, isNameFirst?: boolean, comment?: string | NodeArray<JSDocComment>): JSDocParameterTag {
4707            const node = createBaseJSDocTag<JSDocParameterTag>(SyntaxKind.JSDocParameterTag, tagName ?? createIdentifier("param"), comment);
4708            node.typeExpression = typeExpression;
4709            node.name = name;
4710            node.isNameFirst = !!isNameFirst;
4711            node.isBracketed = isBracketed;
4712            return node;
4713        }
4714
4715        // @api
4716        function updateJSDocParameterTag(node: JSDocParameterTag, tagName: Identifier = getDefaultTagName(node), name: EntityName, isBracketed: boolean, typeExpression: JSDocTypeExpression | undefined, isNameFirst: boolean, comment: string | NodeArray<JSDocComment> | undefined): JSDocParameterTag {
4717            return node.tagName !== tagName
4718                || node.name !== name
4719                || node.isBracketed !== isBracketed
4720                || node.typeExpression !== typeExpression
4721                || node.isNameFirst !== isNameFirst
4722                || node.comment !== comment
4723                ? update(createJSDocParameterTag(tagName, name, isBracketed, typeExpression, isNameFirst, comment), node)
4724                : node;
4725        }
4726
4727        // @api
4728        function createJSDocPropertyTag(tagName: Identifier | undefined, name: EntityName, isBracketed: boolean, typeExpression?: JSDocTypeExpression, isNameFirst?: boolean, comment?: string | NodeArray<JSDocComment>): JSDocPropertyTag {
4729            const node = createBaseJSDocTag<JSDocPropertyTag>(SyntaxKind.JSDocPropertyTag, tagName ?? createIdentifier("prop"), comment);
4730            node.typeExpression = typeExpression;
4731            node.name = name;
4732            node.isNameFirst = !!isNameFirst;
4733            node.isBracketed = isBracketed;
4734            return node;
4735        }
4736
4737        // @api
4738        function updateJSDocPropertyTag(node: JSDocPropertyTag, tagName: Identifier = getDefaultTagName(node), name: EntityName, isBracketed: boolean, typeExpression: JSDocTypeExpression | undefined, isNameFirst: boolean, comment: string | NodeArray<JSDocComment> | undefined): JSDocPropertyTag {
4739            return node.tagName !== tagName
4740                || node.name !== name
4741                || node.isBracketed !== isBracketed
4742                || node.typeExpression !== typeExpression
4743                || node.isNameFirst !== isNameFirst
4744                || node.comment !== comment
4745                ? update(createJSDocPropertyTag(tagName, name, isBracketed, typeExpression, isNameFirst, comment), node)
4746                : node;
4747        }
4748
4749        // @api
4750        function createJSDocCallbackTag(tagName: Identifier | undefined, typeExpression: JSDocSignature, fullName?: Identifier | JSDocNamespaceDeclaration, comment?: string | NodeArray<JSDocComment>): JSDocCallbackTag {
4751            const node = createBaseJSDocTag<JSDocCallbackTag>(SyntaxKind.JSDocCallbackTag, tagName ?? createIdentifier("callback"), comment);
4752            node.typeExpression = typeExpression;
4753            node.fullName = fullName;
4754            node.name = getJSDocTypeAliasName(fullName);
4755            return node;
4756        }
4757
4758        // @api
4759        function updateJSDocCallbackTag(node: JSDocCallbackTag, tagName: Identifier = getDefaultTagName(node), typeExpression: JSDocSignature, fullName: Identifier | JSDocNamespaceDeclaration | undefined, comment: string | NodeArray<JSDocComment> | undefined): JSDocCallbackTag {
4760            return node.tagName !== tagName
4761                || node.typeExpression !== typeExpression
4762                || node.fullName !== fullName
4763                || node.comment !== comment
4764                ? update(createJSDocCallbackTag(tagName, typeExpression, fullName, comment), node)
4765                : node;
4766        }
4767
4768        // @api
4769        function createJSDocAugmentsTag(tagName: Identifier | undefined, className: JSDocAugmentsTag["class"], comment?: string | NodeArray<JSDocComment>): JSDocAugmentsTag {
4770            const node = createBaseJSDocTag<JSDocAugmentsTag>(SyntaxKind.JSDocAugmentsTag, tagName ?? createIdentifier("augments"), comment);
4771            node.class = className;
4772            return node;
4773        }
4774
4775        // @api
4776        function updateJSDocAugmentsTag(node: JSDocAugmentsTag, tagName: Identifier = getDefaultTagName(node), className: JSDocAugmentsTag["class"], comment: string | NodeArray<JSDocComment> | undefined): JSDocAugmentsTag {
4777            return node.tagName !== tagName
4778                || node.class !== className
4779                || node.comment !== comment
4780                ? update(createJSDocAugmentsTag(tagName, className, comment), node)
4781                : node;
4782        }
4783
4784        // @api
4785        function createJSDocImplementsTag(tagName: Identifier | undefined, className: JSDocImplementsTag["class"], comment?: string | NodeArray<JSDocComment>): JSDocImplementsTag {
4786            const node = createBaseJSDocTag<JSDocImplementsTag>(SyntaxKind.JSDocImplementsTag, tagName ?? createIdentifier("implements"), comment);
4787            node.class = className;
4788            return node;
4789        }
4790
4791        // @api
4792        function createJSDocSeeTag(tagName: Identifier | undefined, name: JSDocNameReference | undefined, comment?: string | NodeArray<JSDocComment>): JSDocSeeTag {
4793            const node = createBaseJSDocTag<JSDocSeeTag>(SyntaxKind.JSDocSeeTag, tagName ?? createIdentifier("see"), comment);
4794            node.name = name;
4795            return node;
4796        }
4797
4798        // @api
4799        function updateJSDocSeeTag(node: JSDocSeeTag, tagName: Identifier | undefined, name: JSDocNameReference | undefined, comment?: string | NodeArray<JSDocComment>): JSDocSeeTag {
4800            return node.tagName !== tagName
4801                || node.name !== name
4802                || node.comment !== comment
4803                ? update(createJSDocSeeTag(tagName, name, comment), node)
4804                : node;
4805        }
4806
4807        // @api
4808        function createJSDocNameReference(name: EntityName | JSDocMemberName): JSDocNameReference {
4809            const node = createBaseNode<JSDocNameReference>(SyntaxKind.JSDocNameReference);
4810            node.name = name;
4811            return node;
4812        }
4813
4814        // @api
4815        function updateJSDocNameReference(node: JSDocNameReference, name: EntityName | JSDocMemberName): JSDocNameReference {
4816            return node.name !== name
4817                ? update(createJSDocNameReference(name), node)
4818                : node;
4819        }
4820
4821        // @api
4822        function createJSDocMemberName(left: EntityName | JSDocMemberName, right: Identifier) {
4823            const node = createBaseNode<JSDocMemberName>(SyntaxKind.JSDocMemberName);
4824            node.left = left;
4825            node.right = right;
4826            node.transformFlags |=
4827                propagateChildFlags(node.left) |
4828                propagateChildFlags(node.right);
4829            return node;
4830        }
4831
4832        // @api
4833        function updateJSDocMemberName(node: JSDocMemberName, left: EntityName | JSDocMemberName, right: Identifier) {
4834            return node.left !== left
4835                || node.right !== right
4836                ? update(createJSDocMemberName(left, right), node)
4837                : node;
4838        }
4839
4840        // @api
4841        function createJSDocLink(name: EntityName | JSDocMemberName | undefined, text: string): JSDocLink {
4842            const node = createBaseNode<JSDocLink>(SyntaxKind.JSDocLink);
4843            node.name = name;
4844            node.text = text;
4845            return node;
4846        }
4847
4848        // @api
4849        function updateJSDocLink(node: JSDocLink, name: EntityName | JSDocMemberName | undefined, text: string): JSDocLink {
4850            return node.name !== name
4851                ? update(createJSDocLink(name, text), node)
4852                : node;
4853        }
4854
4855        // @api
4856        function createJSDocLinkCode(name: EntityName | JSDocMemberName | undefined, text: string): JSDocLinkCode {
4857            const node = createBaseNode<JSDocLinkCode>(SyntaxKind.JSDocLinkCode);
4858            node.name = name;
4859            node.text = text;
4860            return node;
4861        }
4862
4863        // @api
4864        function updateJSDocLinkCode(node: JSDocLinkCode, name: EntityName | JSDocMemberName | undefined, text: string): JSDocLinkCode {
4865            return node.name !== name
4866                ? update(createJSDocLinkCode(name, text), node)
4867                : node;
4868        }
4869
4870        // @api
4871        function createJSDocLinkPlain(name: EntityName | JSDocMemberName | undefined, text: string): JSDocLinkPlain {
4872            const node = createBaseNode<JSDocLinkPlain>(SyntaxKind.JSDocLinkPlain);
4873            node.name = name;
4874            node.text = text;
4875            return node;
4876        }
4877
4878        // @api
4879        function updateJSDocLinkPlain(node: JSDocLinkPlain, name: EntityName | JSDocMemberName | undefined, text: string): JSDocLinkPlain {
4880            return node.name !== name
4881                ? update(createJSDocLinkPlain(name, text), node)
4882                : node;
4883        }
4884
4885        // @api
4886        function updateJSDocImplementsTag(node: JSDocImplementsTag, tagName: Identifier = getDefaultTagName(node), className: JSDocImplementsTag["class"], comment: string | NodeArray<JSDocComment> | undefined): JSDocImplementsTag {
4887            return node.tagName !== tagName
4888                || node.class !== className
4889                || node.comment !== comment
4890                ? update(createJSDocImplementsTag(tagName, className, comment), node)
4891                : node;
4892        }
4893
4894        // @api
4895        // createJSDocAuthorTag
4896        // createJSDocClassTag
4897        // createJSDocPublicTag
4898        // createJSDocPrivateTag
4899        // createJSDocProtectedTag
4900        // createJSDocReadonlyTag
4901        // createJSDocDeprecatedTag
4902        function createJSDocSimpleTagWorker<T extends JSDocTag>(kind: T["kind"], tagName: Identifier | undefined, comment?: string | NodeArray<JSDocComment>) {
4903            const node = createBaseJSDocTag<T>(kind, tagName ?? createIdentifier(getDefaultTagNameForKind(kind)), comment);
4904            return node;
4905        }
4906
4907        // @api
4908        // updateJSDocAuthorTag
4909        // updateJSDocClassTag
4910        // updateJSDocPublicTag
4911        // updateJSDocPrivateTag
4912        // updateJSDocProtectedTag
4913        // updateJSDocReadonlyTag
4914        // updateJSDocDeprecatedTag
4915        function updateJSDocSimpleTagWorker<T extends JSDocTag>(kind: T["kind"], node: T, tagName: Identifier = getDefaultTagName(node), comment: string | NodeArray<JSDocComment> | undefined) {
4916            return node.tagName !== tagName
4917                || node.comment !== comment
4918                ? update(createJSDocSimpleTagWorker(kind, tagName, comment), node) :
4919                node;
4920        }
4921
4922        // @api
4923        // createJSDocTypeTag
4924        // createJSDocReturnTag
4925        // createJSDocThisTag
4926        // createJSDocEnumTag
4927        function createJSDocTypeLikeTagWorker<T extends JSDocTag & { typeExpression?: JSDocTypeExpression }>(kind: T["kind"], tagName: Identifier | undefined, typeExpression?: JSDocTypeExpression, comment?: string | NodeArray<JSDocComment>) {
4928            const node = createBaseJSDocTag<T>(kind, tagName ?? createIdentifier(getDefaultTagNameForKind(kind)), comment);
4929            node.typeExpression = typeExpression;
4930            return node;
4931        }
4932
4933        // @api
4934        // updateJSDocTypeTag
4935        // updateJSDocReturnTag
4936        // updateJSDocThisTag
4937        // updateJSDocEnumTag
4938        function updateJSDocTypeLikeTagWorker<T extends JSDocTag & { typeExpression?: JSDocTypeExpression }>(kind: T["kind"], node: T, tagName: Identifier = getDefaultTagName(node), typeExpression: JSDocTypeExpression | undefined, comment: string | NodeArray<JSDocComment> | undefined) {
4939            return node.tagName !== tagName
4940                || node.typeExpression !== typeExpression
4941                || node.comment !== comment
4942                ? update(createJSDocTypeLikeTagWorker(kind, tagName, typeExpression, comment), node)
4943                : node;
4944        }
4945
4946        // @api
4947        function createJSDocUnknownTag(tagName: Identifier, comment?: string | NodeArray<JSDocComment>): JSDocUnknownTag {
4948            const node = createBaseJSDocTag<JSDocUnknownTag>(SyntaxKind.JSDocTag, tagName, comment);
4949            return node;
4950        }
4951
4952        // @api
4953        function updateJSDocUnknownTag(node: JSDocUnknownTag, tagName: Identifier, comment: string | NodeArray<JSDocComment> | undefined): JSDocUnknownTag {
4954            return node.tagName !== tagName
4955                || node.comment !== comment
4956                ? update(createJSDocUnknownTag(tagName, comment), node)
4957                : node;
4958        }
4959
4960        // @api
4961        function createJSDocText(text: string): JSDocText {
4962            const node = createBaseNode<JSDocText>(SyntaxKind.JSDocText);
4963            node.text = text;
4964            return node;
4965        }
4966
4967        // @api
4968        function updateJSDocText(node: JSDocText, text: string): JSDocText {
4969            return node.text !== text
4970                ? update(createJSDocText(text), node)
4971                : node;
4972        }
4973
4974        // @api
4975        function createJSDocComment(comment?: string | NodeArray<JSDocComment> | undefined, tags?: readonly JSDocTag[] | undefined) {
4976            const node = createBaseNode<JSDoc>(SyntaxKind.JSDoc);
4977            node.comment = comment;
4978            node.tags = asNodeArray(tags);
4979            return node;
4980        }
4981
4982        // @api
4983        function updateJSDocComment(node: JSDoc, comment: string | NodeArray<JSDocComment> | undefined, tags: readonly JSDocTag[] | undefined) {
4984            return node.comment !== comment
4985                || node.tags !== tags
4986                ? update(createJSDocComment(comment, tags), node)
4987                : node;
4988        }
4989
4990        //
4991        // JSX
4992        //
4993
4994        // @api
4995        function createJsxElement(openingElement: JsxOpeningElement, children: readonly JsxChild[], closingElement: JsxClosingElement) {
4996            const node = createBaseNode<JsxElement>(SyntaxKind.JsxElement);
4997            node.openingElement = openingElement;
4998            node.children = createNodeArray(children);
4999            node.closingElement = closingElement;
5000            node.transformFlags |=
5001                propagateChildFlags(node.openingElement) |
5002                propagateChildrenFlags(node.children) |
5003                propagateChildFlags(node.closingElement) |
5004                TransformFlags.ContainsJsx;
5005            return node;
5006        }
5007
5008        // @api
5009        function updateJsxElement(node: JsxElement, openingElement: JsxOpeningElement, children: readonly JsxChild[], closingElement: JsxClosingElement) {
5010            return node.openingElement !== openingElement
5011                || node.children !== children
5012                || node.closingElement !== closingElement
5013                ? update(createJsxElement(openingElement, children, closingElement), node)
5014                : node;
5015        }
5016
5017        // @api
5018        function createJsxSelfClosingElement(tagName: JsxTagNameExpression, typeArguments: readonly TypeNode[] | undefined, attributes: JsxAttributes) {
5019            const node = createBaseNode<JsxSelfClosingElement>(SyntaxKind.JsxSelfClosingElement);
5020            node.tagName = tagName;
5021            node.typeArguments = asNodeArray(typeArguments);
5022            node.attributes = attributes;
5023            node.transformFlags |=
5024                propagateChildFlags(node.tagName) |
5025                propagateChildrenFlags(node.typeArguments) |
5026                propagateChildFlags(node.attributes) |
5027                TransformFlags.ContainsJsx;
5028            if (node.typeArguments) {
5029                node.transformFlags |= TransformFlags.ContainsTypeScript;
5030            }
5031            return node;
5032        }
5033
5034        // @api
5035        function updateJsxSelfClosingElement(node: JsxSelfClosingElement, tagName: JsxTagNameExpression, typeArguments: readonly TypeNode[] | undefined, attributes: JsxAttributes) {
5036            return node.tagName !== tagName
5037                || node.typeArguments !== typeArguments
5038                || node.attributes !== attributes
5039                ? update(createJsxSelfClosingElement(tagName, typeArguments, attributes), node)
5040                : node;
5041        }
5042
5043        // @api
5044        function createJsxOpeningElement(tagName: JsxTagNameExpression, typeArguments: readonly TypeNode[] | undefined, attributes: JsxAttributes) {
5045            const node = createBaseNode<JsxOpeningElement>(SyntaxKind.JsxOpeningElement);
5046            node.tagName = tagName;
5047            node.typeArguments = asNodeArray(typeArguments);
5048            node.attributes = attributes;
5049            node.transformFlags |=
5050                propagateChildFlags(node.tagName) |
5051                propagateChildrenFlags(node.typeArguments) |
5052                propagateChildFlags(node.attributes) |
5053                TransformFlags.ContainsJsx;
5054            if (typeArguments) {
5055                node.transformFlags |= TransformFlags.ContainsTypeScript;
5056            }
5057            return node;
5058        }
5059
5060        // @api
5061        function updateJsxOpeningElement(node: JsxOpeningElement, tagName: JsxTagNameExpression, typeArguments: readonly TypeNode[] | undefined, attributes: JsxAttributes) {
5062            return node.tagName !== tagName
5063                || node.typeArguments !== typeArguments
5064                || node.attributes !== attributes
5065                ? update(createJsxOpeningElement(tagName, typeArguments, attributes), node)
5066                : node;
5067        }
5068
5069        // @api
5070        function createJsxClosingElement(tagName: JsxTagNameExpression) {
5071            const node = createBaseNode<JsxClosingElement>(SyntaxKind.JsxClosingElement);
5072            node.tagName = tagName;
5073            node.transformFlags |=
5074                propagateChildFlags(node.tagName) |
5075                TransformFlags.ContainsJsx;
5076            return node;
5077        }
5078
5079        // @api
5080        function updateJsxClosingElement(node: JsxClosingElement, tagName: JsxTagNameExpression) {
5081            return node.tagName !== tagName
5082                ? update(createJsxClosingElement(tagName), node)
5083                : node;
5084        }
5085
5086        // @api
5087        function createJsxFragment(openingFragment: JsxOpeningFragment, children: readonly JsxChild[], closingFragment: JsxClosingFragment) {
5088            const node = createBaseNode<JsxFragment>(SyntaxKind.JsxFragment);
5089            node.openingFragment = openingFragment;
5090            node.children = createNodeArray(children);
5091            node.closingFragment = closingFragment;
5092            node.transformFlags |=
5093                propagateChildFlags(node.openingFragment) |
5094                propagateChildrenFlags(node.children) |
5095                propagateChildFlags(node.closingFragment) |
5096                TransformFlags.ContainsJsx;
5097            return node;
5098        }
5099
5100        // @api
5101        function updateJsxFragment(node: JsxFragment, openingFragment: JsxOpeningFragment, children: readonly JsxChild[], closingFragment: JsxClosingFragment) {
5102            return node.openingFragment !== openingFragment
5103                || node.children !== children
5104                || node.closingFragment !== closingFragment
5105                ? update(createJsxFragment(openingFragment, children, closingFragment), node)
5106                : node;
5107        }
5108
5109        // @api
5110        function createJsxText(text: string, containsOnlyTriviaWhiteSpaces?: boolean) {
5111            const node = createBaseNode<JsxText>(SyntaxKind.JsxText);
5112            node.text = text;
5113            node.containsOnlyTriviaWhiteSpaces = !!containsOnlyTriviaWhiteSpaces;
5114            node.transformFlags |= TransformFlags.ContainsJsx;
5115            return node;
5116        }
5117
5118        // @api
5119        function updateJsxText(node: JsxText, text: string, containsOnlyTriviaWhiteSpaces?: boolean) {
5120            return node.text !== text
5121                || node.containsOnlyTriviaWhiteSpaces !== containsOnlyTriviaWhiteSpaces
5122                ? update(createJsxText(text, containsOnlyTriviaWhiteSpaces), node)
5123                : node;
5124        }
5125
5126        // @api
5127        function createJsxOpeningFragment() {
5128            const node = createBaseNode<JsxOpeningFragment>(SyntaxKind.JsxOpeningFragment);
5129            node.transformFlags |= TransformFlags.ContainsJsx;
5130            return node;
5131        }
5132
5133        // @api
5134        function createJsxJsxClosingFragment() {
5135            const node = createBaseNode<JsxClosingFragment>(SyntaxKind.JsxClosingFragment);
5136            node.transformFlags |= TransformFlags.ContainsJsx;
5137            return node;
5138        }
5139
5140        // @api
5141        function createJsxAttribute(name: Identifier, initializer: JsxAttributeValue | undefined) {
5142            const node = createBaseNode<JsxAttribute>(SyntaxKind.JsxAttribute);
5143            node.name = name;
5144            node.initializer = initializer;
5145            node.transformFlags |=
5146                propagateChildFlags(node.name) |
5147                propagateChildFlags(node.initializer) |
5148                TransformFlags.ContainsJsx;
5149            return node;
5150        }
5151
5152        // @api
5153        function updateJsxAttribute(node: JsxAttribute, name: Identifier, initializer: JsxAttributeValue | undefined) {
5154            return node.name !== name
5155                || node.initializer !== initializer
5156                ? update(createJsxAttribute(name, initializer), node)
5157                : node;
5158        }
5159
5160        // @api
5161        function createJsxAttributes(properties: readonly JsxAttributeLike[]) {
5162            const node = createBaseNode<JsxAttributes>(SyntaxKind.JsxAttributes);
5163            node.properties = createNodeArray(properties);
5164            node.transformFlags |=
5165                propagateChildrenFlags(node.properties) |
5166                TransformFlags.ContainsJsx;
5167            return node;
5168        }
5169
5170        // @api
5171        function updateJsxAttributes(node: JsxAttributes, properties: readonly JsxAttributeLike[]) {
5172            return node.properties !== properties
5173                ? update(createJsxAttributes(properties), node)
5174                : node;
5175        }
5176
5177        // @api
5178        function createJsxSpreadAttribute(expression: Expression) {
5179            const node = createBaseNode<JsxSpreadAttribute>(SyntaxKind.JsxSpreadAttribute);
5180            node.expression = expression;
5181            node.transformFlags |=
5182                propagateChildFlags(node.expression) |
5183                TransformFlags.ContainsJsx;
5184            return node;
5185        }
5186
5187        // @api
5188        function updateJsxSpreadAttribute(node: JsxSpreadAttribute, expression: Expression) {
5189            return node.expression !== expression
5190                ? update(createJsxSpreadAttribute(expression), node)
5191                : node;
5192        }
5193
5194        // @api
5195        function createJsxExpression(dotDotDotToken: DotDotDotToken | undefined, expression: Expression | undefined) {
5196            const node = createBaseNode<JsxExpression>(SyntaxKind.JsxExpression);
5197            node.dotDotDotToken = dotDotDotToken;
5198            node.expression = expression;
5199            node.transformFlags |=
5200                propagateChildFlags(node.dotDotDotToken) |
5201                propagateChildFlags(node.expression) |
5202                TransformFlags.ContainsJsx;
5203            return node;
5204        }
5205
5206        // @api
5207        function updateJsxExpression(node: JsxExpression, expression: Expression | undefined) {
5208            return node.expression !== expression
5209                ? update(createJsxExpression(node.dotDotDotToken, expression), node)
5210                : node;
5211        }
5212
5213        //
5214        // Clauses
5215        //
5216
5217        // @api
5218        function createCaseClause(expression: Expression, statements: readonly Statement[]) {
5219            const node = createBaseNode<CaseClause>(SyntaxKind.CaseClause);
5220            node.expression = parenthesizerRules().parenthesizeExpressionForDisallowedComma(expression);
5221            node.statements = createNodeArray(statements);
5222            node.transformFlags |=
5223                propagateChildFlags(node.expression) |
5224                propagateChildrenFlags(node.statements);
5225            return node;
5226        }
5227
5228        // @api
5229        function updateCaseClause(node: CaseClause, expression: Expression, statements: readonly Statement[]) {
5230            return node.expression !== expression
5231                || node.statements !== statements
5232                ? update(createCaseClause(expression, statements), node)
5233                : node;
5234        }
5235
5236        // @api
5237        function createDefaultClause(statements: readonly Statement[]) {
5238            const node = createBaseNode<DefaultClause>(SyntaxKind.DefaultClause);
5239            node.statements = createNodeArray(statements);
5240            node.transformFlags = propagateChildrenFlags(node.statements);
5241            return node;
5242        }
5243
5244        // @api
5245        function updateDefaultClause(node: DefaultClause, statements: readonly Statement[]) {
5246            return node.statements !== statements
5247                ? update(createDefaultClause(statements), node)
5248                : node;
5249        }
5250
5251        // @api
5252        function createHeritageClause(token: HeritageClause["token"], types: readonly ExpressionWithTypeArguments[]) {
5253            const node = createBaseNode<HeritageClause>(SyntaxKind.HeritageClause);
5254            node.token = token;
5255            node.types = createNodeArray(types);
5256            node.transformFlags |= propagateChildrenFlags(node.types);
5257            switch (token) {
5258                case SyntaxKind.ExtendsKeyword:
5259                    node.transformFlags |= TransformFlags.ContainsES2015;
5260                    break;
5261                case SyntaxKind.ImplementsKeyword:
5262                    node.transformFlags |= TransformFlags.ContainsTypeScript;
5263                    break;
5264                default:
5265                    return Debug.assertNever(token);
5266            }
5267            return node;
5268        }
5269
5270        // @api
5271        function updateHeritageClause(node: HeritageClause, types: readonly ExpressionWithTypeArguments[]) {
5272            return node.types !== types
5273                ? update(createHeritageClause(node.token, types), node)
5274                : node;
5275        }
5276
5277        // @api
5278        function createCatchClause(variableDeclaration: string | BindingName | VariableDeclaration | undefined, block: Block) {
5279            const node = createBaseNode<CatchClause>(SyntaxKind.CatchClause);
5280            if (typeof variableDeclaration === "string" || variableDeclaration && !isVariableDeclaration(variableDeclaration)) {
5281                variableDeclaration = createVariableDeclaration(
5282                    variableDeclaration,
5283                    /*exclamationToken*/ undefined,
5284                    /*type*/ undefined,
5285                    /*initializer*/ undefined
5286                );
5287            }
5288            node.variableDeclaration = variableDeclaration;
5289            node.block = block;
5290            node.transformFlags |=
5291                propagateChildFlags(node.variableDeclaration) |
5292                propagateChildFlags(node.block);
5293            if (!variableDeclaration) node.transformFlags |= TransformFlags.ContainsES2019;
5294            return node;
5295        }
5296
5297        // @api
5298        function updateCatchClause(node: CatchClause, variableDeclaration: VariableDeclaration | undefined, block: Block) {
5299            return node.variableDeclaration !== variableDeclaration
5300                || node.block !== block
5301                ? update(createCatchClause(variableDeclaration, block), node)
5302                : node;
5303        }
5304
5305        //
5306        // Property assignments
5307        //
5308
5309        // @api
5310        function createPropertyAssignment(name: string | PropertyName, initializer: Expression) {
5311            const node = createBaseNamedDeclaration<PropertyAssignment>(
5312                SyntaxKind.PropertyAssignment,
5313                /*modifiers*/ undefined,
5314                name
5315            );
5316            node.initializer = parenthesizerRules().parenthesizeExpressionForDisallowedComma(initializer);
5317            node.transformFlags |=
5318                propagateChildFlags(node.name) |
5319                propagateChildFlags(node.initializer);
5320
5321            // The following properties are used only to report grammar errors
5322            node.illegalDecorators = undefined;
5323            node.modifiers = undefined;
5324            node.questionToken = undefined;
5325            node.exclamationToken = undefined;
5326            return node;
5327        }
5328
5329        // @api
5330        function updatePropertyAssignment(node: PropertyAssignment, name: PropertyName, initializer: Expression) {
5331            return node.name !== name
5332                || node.initializer !== initializer
5333                ? finishUpdatePropertyAssignment(createPropertyAssignment(name, initializer), node)
5334                : node;
5335        }
5336
5337        function finishUpdatePropertyAssignment(updated: Mutable<PropertyAssignment>, original: PropertyAssignment) {
5338            // copy children used only for error reporting
5339            if (updated !== original) {
5340                updated.illegalDecorators = original.illegalDecorators;
5341                updated.modifiers = original.modifiers;
5342                updated.questionToken = original.questionToken;
5343                updated.exclamationToken = original.exclamationToken;
5344            }
5345            return update(updated, original);
5346        }
5347
5348        // @api
5349        function createShorthandPropertyAssignment(name: string | Identifier, objectAssignmentInitializer?: Expression) {
5350            const node = createBaseNamedDeclaration<ShorthandPropertyAssignment>(
5351                SyntaxKind.ShorthandPropertyAssignment,
5352                /*modifiers*/ undefined,
5353                name
5354            );
5355            node.objectAssignmentInitializer = objectAssignmentInitializer && parenthesizerRules().parenthesizeExpressionForDisallowedComma(objectAssignmentInitializer);
5356            node.transformFlags |=
5357                propagateChildFlags(node.objectAssignmentInitializer) |
5358                TransformFlags.ContainsES2015;
5359
5360            // The following properties are used only to report grammar errors
5361            node.equalsToken = undefined;
5362            node.illegalDecorators = undefined;
5363            node.modifiers = undefined;
5364            node.questionToken = undefined;
5365            node.exclamationToken = undefined;
5366            return node;
5367        }
5368
5369        // @api
5370        function updateShorthandPropertyAssignment(node: ShorthandPropertyAssignment, name: Identifier, objectAssignmentInitializer: Expression | undefined) {
5371            return node.name !== name
5372                || node.objectAssignmentInitializer !== objectAssignmentInitializer
5373                ? finishUpdateShorthandPropertyAssignment(createShorthandPropertyAssignment(name, objectAssignmentInitializer), node)
5374                : node;
5375        }
5376
5377        function finishUpdateShorthandPropertyAssignment(updated: Mutable<ShorthandPropertyAssignment>, original: ShorthandPropertyAssignment) {
5378            if (updated !== original) {
5379                // copy children used only for error reporting
5380                updated.equalsToken = original.equalsToken;
5381                updated.illegalDecorators = original.illegalDecorators;
5382                updated.modifiers = original.modifiers;
5383                updated.questionToken = original.questionToken;
5384                updated.exclamationToken = original.exclamationToken;
5385            }
5386            return update(updated, original);
5387        }
5388
5389        // @api
5390        function createSpreadAssignment(expression: Expression) {
5391            const node = createBaseNode<SpreadAssignment>(SyntaxKind.SpreadAssignment);
5392            node.expression = parenthesizerRules().parenthesizeExpressionForDisallowedComma(expression);
5393            node.transformFlags |=
5394                propagateChildFlags(node.expression) |
5395                TransformFlags.ContainsES2018 |
5396                TransformFlags.ContainsObjectRestOrSpread;
5397            return node;
5398        }
5399
5400        // @api
5401        function updateSpreadAssignment(node: SpreadAssignment, expression: Expression) {
5402            return node.expression !== expression
5403                ? update(createSpreadAssignment(expression), node)
5404                : node;
5405        }
5406
5407        //
5408        // Enum
5409        //
5410
5411        // @api
5412        function createEnumMember(name: string | PropertyName, initializer?: Expression) {
5413            const node = createBaseNode<EnumMember>(SyntaxKind.EnumMember);
5414            node.name = asName(name);
5415            node.initializer = initializer && parenthesizerRules().parenthesizeExpressionForDisallowedComma(initializer);
5416            node.transformFlags |=
5417                propagateChildFlags(node.name) |
5418                propagateChildFlags(node.initializer) |
5419                TransformFlags.ContainsTypeScript;
5420            return node;
5421        }
5422
5423        // @api
5424        function updateEnumMember(node: EnumMember, name: PropertyName, initializer: Expression | undefined) {
5425            return node.name !== name
5426                || node.initializer !== initializer
5427                ? update(createEnumMember(name, initializer), node)
5428                : node;
5429        }
5430
5431        //
5432        // Top-level nodes
5433        //
5434
5435        // @api
5436        function createSourceFile(
5437            statements: readonly Statement[],
5438            endOfFileToken: EndOfFileToken,
5439            flags: NodeFlags
5440        ) {
5441            const node = baseFactory.createBaseSourceFileNode(SyntaxKind.SourceFile) as Mutable<SourceFile>;
5442            node.statements = createNodeArray(statements);
5443            node.endOfFileToken = endOfFileToken;
5444            node.flags |= flags;
5445            node.fileName = "";
5446            node.text = "";
5447            node.languageVersion = 0;
5448            node.languageVariant = 0;
5449            node.scriptKind = 0;
5450            node.isDeclarationFile = false;
5451            node.hasNoDefaultLib = false;
5452            node.transformFlags |=
5453                propagateChildrenFlags(node.statements) |
5454                propagateChildFlags(node.endOfFileToken);
5455            return node;
5456        }
5457
5458        function cloneSourceFileWithChanges(
5459            source: SourceFile,
5460            statements: readonly Statement[],
5461            isDeclarationFile: boolean,
5462            referencedFiles: readonly FileReference[],
5463            typeReferences: readonly FileReference[],
5464            hasNoDefaultLib: boolean,
5465            libReferences: readonly FileReference[]
5466        ) {
5467            const node = (source.redirectInfo ? Object.create(source.redirectInfo.redirectTarget) : baseFactory.createBaseSourceFileNode(SyntaxKind.SourceFile)) as Mutable<SourceFile>;
5468            for (const p in source) {
5469                if (p === "emitNode" || hasProperty(node, p) || !hasProperty(source, p)) continue;
5470                (node as any)[p] = (source as any)[p];
5471            }
5472            node.flags |= source.flags;
5473            node.statements = createNodeArray(statements);
5474            node.endOfFileToken = source.endOfFileToken;
5475            node.isDeclarationFile = isDeclarationFile;
5476            node.referencedFiles = referencedFiles;
5477            node.typeReferenceDirectives = typeReferences;
5478            node.hasNoDefaultLib = hasNoDefaultLib;
5479            node.libReferenceDirectives = libReferences;
5480            node.transformFlags =
5481                propagateChildrenFlags(node.statements) |
5482                propagateChildFlags(node.endOfFileToken);
5483            node.impliedNodeFormat = source.impliedNodeFormat;
5484            return node;
5485        }
5486
5487        // @api
5488        function updateSourceFile(
5489            node: SourceFile,
5490            statements: readonly Statement[],
5491            isDeclarationFile = node.isDeclarationFile,
5492            referencedFiles = node.referencedFiles,
5493            typeReferenceDirectives = node.typeReferenceDirectives,
5494            hasNoDefaultLib = node.hasNoDefaultLib,
5495            libReferenceDirectives = node.libReferenceDirectives
5496        ) {
5497            return node.statements !== statements
5498                || node.isDeclarationFile !== isDeclarationFile
5499                || node.referencedFiles !== referencedFiles
5500                || node.typeReferenceDirectives !== typeReferenceDirectives
5501                || node.hasNoDefaultLib !== hasNoDefaultLib
5502                || node.libReferenceDirectives !== libReferenceDirectives
5503                ? update(cloneSourceFileWithChanges(node, statements, isDeclarationFile, referencedFiles, typeReferenceDirectives, hasNoDefaultLib, libReferenceDirectives), node)
5504                : node;
5505        }
5506
5507        // @api
5508        function createBundle(sourceFiles: readonly SourceFile[], prepends: readonly (UnparsedSource | InputFiles)[] = emptyArray) {
5509            const node = createBaseNode<Bundle>(SyntaxKind.Bundle);
5510            node.prepends = prepends;
5511            node.sourceFiles = sourceFiles;
5512            return node;
5513        }
5514
5515        // @api
5516        function updateBundle(node: Bundle, sourceFiles: readonly SourceFile[], prepends: readonly (UnparsedSource | InputFiles)[] = emptyArray) {
5517            return node.sourceFiles !== sourceFiles
5518                || node.prepends !== prepends
5519                ? update(createBundle(sourceFiles, prepends), node)
5520                : node;
5521        }
5522
5523        // @api
5524        function createUnparsedSource(prologues: readonly UnparsedPrologue[], syntheticReferences: readonly UnparsedSyntheticReference[] | undefined, texts: readonly UnparsedSourceText[]) {
5525            const node = createBaseNode<UnparsedSource>(SyntaxKind.UnparsedSource);
5526            node.prologues = prologues;
5527            node.syntheticReferences = syntheticReferences;
5528            node.texts = texts;
5529            node.fileName = "";
5530            node.text = "";
5531            node.referencedFiles = emptyArray;
5532            node.libReferenceDirectives = emptyArray;
5533            node.getLineAndCharacterOfPosition = pos => getLineAndCharacterOfPosition(node, pos);
5534            return node;
5535        }
5536
5537        function createBaseUnparsedNode<T extends UnparsedNode>(kind: T["kind"], data?: string) {
5538            const node = createBaseNode(kind);
5539            node.data = data;
5540            return node;
5541        }
5542
5543        // @api
5544        function createUnparsedPrologue(data?: string): UnparsedPrologue {
5545            return createBaseUnparsedNode(SyntaxKind.UnparsedPrologue, data);
5546        }
5547
5548        // @api
5549        function createUnparsedPrepend(data: string | undefined, texts: readonly UnparsedTextLike[]): UnparsedPrepend {
5550            const node = createBaseUnparsedNode<UnparsedPrepend>(SyntaxKind.UnparsedPrepend, data);
5551            node.texts = texts;
5552            return node;
5553        }
5554
5555        // @api
5556        function createUnparsedTextLike(data: string | undefined, internal: boolean): UnparsedTextLike {
5557            return createBaseUnparsedNode(internal ? SyntaxKind.UnparsedInternalText : SyntaxKind.UnparsedText, data);
5558        }
5559
5560        // @api
5561        function createUnparsedSyntheticReference(section: BundleFileHasNoDefaultLib | BundleFileReference): UnparsedSyntheticReference {
5562            const node = createBaseNode<UnparsedSyntheticReference>(SyntaxKind.UnparsedSyntheticReference);
5563            node.data = section.data;
5564            node.section = section;
5565            return node;
5566        }
5567
5568        // @api
5569        function createInputFiles(): InputFiles {
5570            const node = createBaseNode<InputFiles>(SyntaxKind.InputFiles);
5571            node.javascriptText = "";
5572            node.declarationText = "";
5573            return node;
5574        }
5575
5576        //
5577        // Synthetic Nodes (used by checker)
5578        //
5579
5580        // @api
5581        function createSyntheticExpression(type: Type, isSpread = false, tupleNameSource?: ParameterDeclaration | NamedTupleMember) {
5582            const node = createBaseNode<SyntheticExpression>(SyntaxKind.SyntheticExpression);
5583            node.type = type;
5584            node.isSpread = isSpread;
5585            node.tupleNameSource = tupleNameSource;
5586            return node;
5587        }
5588
5589        // @api
5590        function createSyntaxList(children: Node[]) {
5591            const node = createBaseNode<SyntaxList>(SyntaxKind.SyntaxList);
5592            node._children = children;
5593            return node;
5594        }
5595
5596        //
5597        // Transformation nodes
5598        //
5599
5600        /**
5601         * Creates a synthetic statement to act as a placeholder for a not-emitted statement in
5602         * order to preserve comments.
5603         *
5604         * @param original The original statement.
5605         */
5606        // @api
5607        function createNotEmittedStatement(original: Node) {
5608            const node = createBaseNode<NotEmittedStatement>(SyntaxKind.NotEmittedStatement);
5609            node.original = original;
5610            setTextRange(node, original);
5611            return node;
5612        }
5613
5614        /**
5615         * Creates a synthetic expression to act as a placeholder for a not-emitted expression in
5616         * order to preserve comments or sourcemap positions.
5617         *
5618         * @param expression The inner expression to emit.
5619         * @param original The original outer expression.
5620         */
5621        // @api
5622        function createPartiallyEmittedExpression(expression: Expression, original?: Node) {
5623            const node = createBaseNode<PartiallyEmittedExpression>(SyntaxKind.PartiallyEmittedExpression);
5624            node.expression = expression;
5625            node.original = original;
5626            node.transformFlags |=
5627                propagateChildFlags(node.expression) |
5628                TransformFlags.ContainsTypeScript;
5629            setTextRange(node, original);
5630            return node;
5631        }
5632
5633        // @api
5634        function updatePartiallyEmittedExpression(node: PartiallyEmittedExpression, expression: Expression) {
5635            return node.expression !== expression
5636                ? update(createPartiallyEmittedExpression(expression, node.original), node)
5637                : node;
5638        }
5639
5640        function flattenCommaElements(node: Expression): Expression | readonly Expression[] {
5641            if (nodeIsSynthesized(node) && !isParseTreeNode(node) && !node.original && !node.emitNode && !node.id) {
5642                if (isCommaListExpression(node)) {
5643                    return node.elements;
5644                }
5645                if (isBinaryExpression(node) && isCommaToken(node.operatorToken)) {
5646                    return [node.left, node.right];
5647                }
5648            }
5649            return node;
5650        }
5651
5652        // @api
5653        function createCommaListExpression(elements: readonly Expression[]) {
5654            const node = createBaseNode<CommaListExpression>(SyntaxKind.CommaListExpression);
5655            node.elements = createNodeArray(sameFlatMap(elements, flattenCommaElements));
5656            node.transformFlags |= propagateChildrenFlags(node.elements);
5657            return node;
5658        }
5659
5660        // @api
5661        function updateCommaListExpression(node: CommaListExpression, elements: readonly Expression[]) {
5662            return node.elements !== elements
5663                ? update(createCommaListExpression(elements), node)
5664                : node;
5665        }
5666
5667        /**
5668         * Creates a synthetic element to act as a placeholder for the end of an emitted declaration in
5669         * order to properly emit exports.
5670         */
5671        // @api
5672        function createEndOfDeclarationMarker(original: Node) {
5673            const node = createBaseNode<EndOfDeclarationMarker>(SyntaxKind.EndOfDeclarationMarker);
5674            node.emitNode = {} as EmitNode;
5675            node.original = original;
5676            return node;
5677        }
5678
5679        /**
5680         * Creates a synthetic element to act as a placeholder for the beginning of a merged declaration in
5681         * order to properly emit exports.
5682         */
5683        // @api
5684        function createMergeDeclarationMarker(original: Node) {
5685            const node = createBaseNode<MergeDeclarationMarker>(SyntaxKind.MergeDeclarationMarker);
5686            node.emitNode = {} as EmitNode;
5687            node.original = original;
5688            return node;
5689        }
5690
5691        // @api
5692        function createSyntheticReferenceExpression(expression: Expression, thisArg: Expression) {
5693            const node = createBaseNode<SyntheticReferenceExpression>(SyntaxKind.SyntheticReferenceExpression);
5694            node.expression = expression;
5695            node.thisArg = thisArg;
5696            node.transformFlags |=
5697                propagateChildFlags(node.expression) |
5698                propagateChildFlags(node.thisArg);
5699            return node;
5700        }
5701
5702        // @api
5703        function updateSyntheticReferenceExpression(node: SyntheticReferenceExpression, expression: Expression, thisArg: Expression) {
5704            return node.expression !== expression
5705                || node.thisArg !== thisArg
5706                ? update(createSyntheticReferenceExpression(expression, thisArg), node)
5707                : node;
5708        }
5709
5710        // @api
5711        function cloneNode<T extends Node | undefined>(node: T): T;
5712        function cloneNode<T extends Node>(node: T) {
5713            // We don't use "clone" from core.ts here, as we need to preserve the prototype chain of
5714            // the original node. We also need to exclude specific properties and only include own-
5715            // properties (to skip members already defined on the shared prototype).
5716            if (node === undefined) {
5717                return node;
5718            }
5719
5720            const clone =
5721                isSourceFile(node) ? baseFactory.createBaseSourceFileNode(SyntaxKind.SourceFile) as T :
5722                isIdentifier(node) ? baseFactory.createBaseIdentifierNode(SyntaxKind.Identifier) as T :
5723                isPrivateIdentifier(node) ? baseFactory.createBasePrivateIdentifierNode(SyntaxKind.PrivateIdentifier) as T :
5724                !isNodeKind(node.kind) ? baseFactory.createBaseTokenNode(node.kind) as T :
5725                baseFactory.createBaseNode(node.kind) as T;
5726
5727            (clone as Mutable<T>).flags |= (node.flags & ~NodeFlags.Synthesized);
5728            (clone as Mutable<T>).transformFlags = node.transformFlags;
5729            setOriginalNode(clone, node);
5730
5731            for (const key in node) {
5732                if (hasProperty(clone, key) || !hasProperty(node, key)) {
5733                    continue;
5734                }
5735
5736                clone[key] = node[key];
5737            }
5738
5739            return clone;
5740        }
5741
5742        // compound nodes
5743        function createImmediatelyInvokedFunctionExpression(statements: readonly Statement[]): CallExpression;
5744        function createImmediatelyInvokedFunctionExpression(statements: readonly Statement[], param: ParameterDeclaration, paramValue: Expression): CallExpression;
5745        function createImmediatelyInvokedFunctionExpression(statements: readonly Statement[], param?: ParameterDeclaration, paramValue?: Expression) {
5746            return createCallExpression(
5747                createFunctionExpression(
5748                    /*modifiers*/ undefined,
5749                    /*asteriskToken*/ undefined,
5750                    /*name*/ undefined,
5751                    /*typeParameters*/ undefined,
5752                    /*parameters*/ param ? [param] : [],
5753                    /*type*/ undefined,
5754                    createBlock(statements, /*multiLine*/ true)
5755                ),
5756                /*typeArguments*/ undefined,
5757                /*argumentsArray*/ paramValue ? [paramValue] : []
5758            );
5759        }
5760
5761        function createImmediatelyInvokedArrowFunction(statements: readonly Statement[]): CallExpression;
5762        function createImmediatelyInvokedArrowFunction(statements: readonly Statement[], param: ParameterDeclaration, paramValue: Expression): CallExpression;
5763        function createImmediatelyInvokedArrowFunction(statements: readonly Statement[], param?: ParameterDeclaration, paramValue?: Expression) {
5764            return createCallExpression(
5765                createArrowFunction(
5766                    /*modifiers*/ undefined,
5767                    /*typeParameters*/ undefined,
5768                    /*parameters*/ param ? [param] : [],
5769                    /*type*/ undefined,
5770                    /*equalsGreaterThanToken*/ undefined,
5771                    createBlock(statements, /*multiLine*/ true)
5772                ),
5773                /*typeArguments*/ undefined,
5774                /*argumentsArray*/ paramValue ? [paramValue] : []
5775            );
5776        }
5777
5778        function createVoidZero() {
5779            return createVoidExpression(createNumericLiteral("0"));
5780        }
5781
5782        function createExportDefault(expression: Expression) {
5783            return createExportAssignment(
5784                /*modifiers*/ undefined,
5785                /*isExportEquals*/ false,
5786                expression);
5787        }
5788
5789        function createExternalModuleExport(exportName: Identifier) {
5790            return createExportDeclaration(
5791                /*modifiers*/ undefined,
5792                /*isTypeOnly*/ false,
5793                createNamedExports([
5794                    createExportSpecifier(/*isTypeOnly*/ false, /*propertyName*/ undefined, exportName)
5795                ])
5796            );
5797        }
5798
5799        //
5800        // Utilities
5801        //
5802
5803        function createTypeCheck(value: Expression, tag: TypeOfTag) {
5804            return tag === "undefined"
5805                ? factory.createStrictEquality(value, createVoidZero())
5806                : factory.createStrictEquality(createTypeOfExpression(value), createStringLiteral(tag));
5807        }
5808
5809        function createMethodCall(object: Expression, methodName: string | Identifier, argumentsList: readonly Expression[]) {
5810            // Preserve the optionality of `object`.
5811            if (isCallChain(object)) {
5812                return createCallChain(
5813                    createPropertyAccessChain(object, /*questionDotToken*/ undefined, methodName),
5814                    /*questionDotToken*/ undefined,
5815                    /*typeArguments*/ undefined,
5816                    argumentsList
5817                );
5818            }
5819            return createCallExpression(
5820                createPropertyAccessExpression(object, methodName),
5821                /*typeArguments*/ undefined,
5822                argumentsList
5823            );
5824        }
5825
5826        function createFunctionBindCall(target: Expression, thisArg: Expression, argumentsList: readonly Expression[]) {
5827            return createMethodCall(target, "bind", [thisArg, ...argumentsList]);
5828        }
5829
5830        function createFunctionCallCall(target: Expression, thisArg: Expression, argumentsList: readonly Expression[]) {
5831            return createMethodCall(target, "call", [thisArg, ...argumentsList]);
5832        }
5833
5834        function createFunctionApplyCall(target: Expression, thisArg: Expression, argumentsExpression: Expression) {
5835            return createMethodCall(target, "apply", [thisArg, argumentsExpression]);
5836        }
5837
5838        function createGlobalMethodCall(globalObjectName: string, methodName: string, argumentsList: readonly Expression[]) {
5839            return createMethodCall(createIdentifier(globalObjectName), methodName, argumentsList);
5840        }
5841
5842        function createArraySliceCall(array: Expression, start?: number | Expression) {
5843            return createMethodCall(array, "slice", start === undefined ? [] : [asExpression(start)]);
5844        }
5845
5846        function createArrayConcatCall(array: Expression, argumentsList: readonly Expression[]) {
5847            return createMethodCall(array, "concat", argumentsList);
5848        }
5849
5850        function createObjectDefinePropertyCall(target: Expression, propertyName: string | Expression, attributes: Expression) {
5851            return createGlobalMethodCall("Object", "defineProperty", [target, asExpression(propertyName), attributes]);
5852        }
5853
5854        function createReflectGetCall(target: Expression, propertyKey: Expression, receiver?: Expression): CallExpression {
5855            return createGlobalMethodCall("Reflect", "get", receiver ? [target, propertyKey, receiver] : [target, propertyKey]);
5856        }
5857
5858        function createReflectSetCall(target: Expression, propertyKey: Expression, value: Expression, receiver?: Expression): CallExpression {
5859            return createGlobalMethodCall("Reflect", "set", receiver ? [target, propertyKey, value, receiver] : [target, propertyKey, value]);
5860        }
5861
5862        function tryAddPropertyAssignment(properties: Push<PropertyAssignment>, propertyName: string, expression: Expression | undefined) {
5863            if (expression) {
5864                properties.push(createPropertyAssignment(propertyName, expression));
5865                return true;
5866            }
5867            return false;
5868        }
5869
5870        function createPropertyDescriptor(attributes: PropertyDescriptorAttributes, singleLine?: boolean) {
5871            const properties: PropertyAssignment[] = [];
5872            tryAddPropertyAssignment(properties, "enumerable", asExpression(attributes.enumerable));
5873            tryAddPropertyAssignment(properties, "configurable", asExpression(attributes.configurable));
5874
5875            let isData = tryAddPropertyAssignment(properties, "writable", asExpression(attributes.writable));
5876            isData = tryAddPropertyAssignment(properties, "value", attributes.value) || isData;
5877
5878            let isAccessor = tryAddPropertyAssignment(properties, "get", attributes.get);
5879            isAccessor = tryAddPropertyAssignment(properties, "set", attributes.set) || isAccessor;
5880
5881            Debug.assert(!(isData && isAccessor), "A PropertyDescriptor may not be both an accessor descriptor and a data descriptor.");
5882            return createObjectLiteralExpression(properties, !singleLine);
5883        }
5884
5885        function updateOuterExpression(outerExpression: OuterExpression, expression: Expression) {
5886            switch (outerExpression.kind) {
5887                case SyntaxKind.ParenthesizedExpression: return updateParenthesizedExpression(outerExpression, expression);
5888                case SyntaxKind.TypeAssertionExpression: return updateTypeAssertion(outerExpression, outerExpression.type, expression);
5889                case SyntaxKind.AsExpression: return updateAsExpression(outerExpression, expression, outerExpression.type);
5890                case SyntaxKind.SatisfiesExpression: return updateSatisfiesExpression(outerExpression, expression, outerExpression.type);
5891                case SyntaxKind.NonNullExpression: return updateNonNullExpression(outerExpression, expression);
5892                case SyntaxKind.PartiallyEmittedExpression: return updatePartiallyEmittedExpression(outerExpression, expression);
5893            }
5894        }
5895
5896        /**
5897         * Determines whether a node is a parenthesized expression that can be ignored when recreating outer expressions.
5898         *
5899         * A parenthesized expression can be ignored when all of the following are true:
5900         *
5901         * - It's `pos` and `end` are not -1
5902         * - It does not have a custom source map range
5903         * - It does not have a custom comment range
5904         * - It does not have synthetic leading or trailing comments
5905         *
5906         * If an outermost parenthesized expression is ignored, but the containing expression requires a parentheses around
5907         * the expression to maintain precedence, a new parenthesized expression should be created automatically when
5908         * the containing expression is created/updated.
5909         */
5910        function isIgnorableParen(node: Expression) {
5911            return isParenthesizedExpression(node)
5912                && nodeIsSynthesized(node)
5913                && nodeIsSynthesized(getSourceMapRange(node))
5914                && nodeIsSynthesized(getCommentRange(node))
5915                && !some(getSyntheticLeadingComments(node))
5916                && !some(getSyntheticTrailingComments(node));
5917        }
5918
5919        function restoreOuterExpressions(outerExpression: Expression | undefined, innerExpression: Expression, kinds = OuterExpressionKinds.All): Expression {
5920            if (outerExpression && isOuterExpression(outerExpression, kinds) && !isIgnorableParen(outerExpression)) {
5921                return updateOuterExpression(
5922                    outerExpression,
5923                    restoreOuterExpressions(outerExpression.expression, innerExpression)
5924                );
5925            }
5926            return innerExpression;
5927        }
5928
5929        function restoreEnclosingLabel(node: Statement, outermostLabeledStatement: LabeledStatement | undefined, afterRestoreLabelCallback?: (node: LabeledStatement) => void): Statement {
5930            if (!outermostLabeledStatement) {
5931                return node;
5932            }
5933            const updated = updateLabeledStatement(
5934                outermostLabeledStatement,
5935                outermostLabeledStatement.label,
5936                isLabeledStatement(outermostLabeledStatement.statement)
5937                    ? restoreEnclosingLabel(node, outermostLabeledStatement.statement)
5938                    : node
5939            );
5940            if (afterRestoreLabelCallback) {
5941                afterRestoreLabelCallback(outermostLabeledStatement);
5942            }
5943            return updated;
5944        }
5945
5946        function shouldBeCapturedInTempVariable(node: Expression, cacheIdentifiers: boolean): boolean {
5947            const target = skipParentheses(node);
5948            switch (target.kind) {
5949                case SyntaxKind.Identifier:
5950                    return cacheIdentifiers;
5951                case SyntaxKind.ThisKeyword:
5952                case SyntaxKind.NumericLiteral:
5953                case SyntaxKind.BigIntLiteral:
5954                case SyntaxKind.StringLiteral:
5955                    return false;
5956                case SyntaxKind.ArrayLiteralExpression:
5957                    const elements = (target as ArrayLiteralExpression).elements;
5958                    if (elements.length === 0) {
5959                        return false;
5960                    }
5961                    return true;
5962                case SyntaxKind.ObjectLiteralExpression:
5963                    return (target as ObjectLiteralExpression).properties.length > 0;
5964                default:
5965                    return true;
5966            }
5967        }
5968
5969        function createCallBinding(expression: Expression, recordTempVariable: (temp: Identifier) => void, languageVersion?: ScriptTarget, cacheIdentifiers = false): CallBinding {
5970            const callee = skipOuterExpressions(expression, OuterExpressionKinds.All);
5971            let thisArg: Expression;
5972            let target: LeftHandSideExpression;
5973            if (isSuperProperty(callee)) {
5974                thisArg = createThis();
5975                target = callee;
5976            }
5977            else if (isSuperKeyword(callee)) {
5978                thisArg = createThis();
5979                target = languageVersion !== undefined && languageVersion < ScriptTarget.ES2015
5980                    ? setTextRange(createIdentifier("_super"), callee)
5981                    : callee as PrimaryExpression;
5982            }
5983            else if (getEmitFlags(callee) & EmitFlags.HelperName) {
5984                thisArg = createVoidZero();
5985                target = parenthesizerRules().parenthesizeLeftSideOfAccess(callee, /*optionalChain*/ false);
5986            }
5987            else if (isPropertyAccessExpression(callee)) {
5988                if (shouldBeCapturedInTempVariable(callee.expression, cacheIdentifiers)) {
5989                    // for `a.b()` target is `(_a = a).b` and thisArg is `_a`
5990                    thisArg = createTempVariable(recordTempVariable);
5991                    target = createPropertyAccessExpression(
5992                        setTextRange(
5993                            factory.createAssignment(
5994                                thisArg,
5995                                callee.expression
5996                            ),
5997                            callee.expression
5998                        ),
5999                        callee.name
6000                    );
6001                    setTextRange(target, callee);
6002                }
6003                else {
6004                    thisArg = callee.expression;
6005                    target = callee;
6006                }
6007            }
6008            else if (isElementAccessExpression(callee)) {
6009                if (shouldBeCapturedInTempVariable(callee.expression, cacheIdentifiers)) {
6010                    // for `a[b]()` target is `(_a = a)[b]` and thisArg is `_a`
6011                    thisArg = createTempVariable(recordTempVariable);
6012                    target = createElementAccessExpression(
6013                        setTextRange(
6014                            factory.createAssignment(
6015                                thisArg,
6016                                callee.expression
6017                            ),
6018                            callee.expression
6019                        ),
6020                        callee.argumentExpression
6021                    );
6022                    setTextRange(target, callee);
6023                }
6024                else {
6025                    thisArg = callee.expression;
6026                    target = callee;
6027                }
6028            }
6029            else {
6030                // for `a()` target is `a` and thisArg is `void 0`
6031                thisArg = createVoidZero();
6032                target = parenthesizerRules().parenthesizeLeftSideOfAccess(expression, /*optionalChain*/ false);
6033            }
6034
6035            return { target, thisArg };
6036        }
6037
6038        function createAssignmentTargetWrapper(paramName: Identifier, expression: Expression): LeftHandSideExpression {
6039            return createPropertyAccessExpression(
6040                // Explicit parens required because of v8 regression (https://bugs.chromium.org/p/v8/issues/detail?id=9560)
6041                createParenthesizedExpression(
6042                    createObjectLiteralExpression([
6043                        createSetAccessorDeclaration(
6044                            /*modifiers*/ undefined,
6045                            "value",
6046                            [createParameterDeclaration(
6047                                /*modifiers*/ undefined,
6048                                /*dotDotDotToken*/ undefined,
6049                                paramName,
6050                                /*questionToken*/ undefined,
6051                                /*type*/ undefined,
6052                                /*initializer*/ undefined
6053                            )],
6054                            createBlock([
6055                                createExpressionStatement(expression)
6056                            ])
6057                        )
6058                    ])
6059                ),
6060                "value"
6061            );
6062        }
6063
6064        function inlineExpressions(expressions: readonly Expression[]) {
6065            // Avoid deeply nested comma expressions as traversing them during emit can result in "Maximum call
6066            // stack size exceeded" errors.
6067            return expressions.length > 10
6068                ? createCommaListExpression(expressions)
6069                : reduceLeft(expressions, factory.createComma)!;
6070        }
6071
6072        function getName(node: Declaration | undefined, allowComments?: boolean, allowSourceMaps?: boolean, emitFlags: EmitFlags = 0) {
6073            const nodeName = getNameOfDeclaration(node);
6074            if (nodeName && isIdentifier(nodeName) && !isGeneratedIdentifier(nodeName)) {
6075                // TODO(rbuckton): Does this need to be parented?
6076                const name = setParent(setTextRange(cloneNode(nodeName), nodeName), nodeName.parent);
6077                emitFlags |= getEmitFlags(nodeName);
6078                if (!allowSourceMaps) emitFlags |= EmitFlags.NoSourceMap;
6079                if (!allowComments) emitFlags |= EmitFlags.NoComments;
6080                if (emitFlags) setEmitFlags(name, emitFlags);
6081                return name;
6082            }
6083            return getGeneratedNameForNode(node);
6084        }
6085
6086        /**
6087         * Gets the internal name of a declaration. This is primarily used for declarations that can be
6088         * referred to by name in the body of an ES5 class function body. An internal name will *never*
6089         * be prefixed with an module or namespace export modifier like "exports." when emitted as an
6090         * expression. An internal name will also *never* be renamed due to a collision with a block
6091         * scoped variable.
6092         *
6093         * @param node The declaration.
6094         * @param allowComments A value indicating whether comments may be emitted for the name.
6095         * @param allowSourceMaps A value indicating whether source maps may be emitted for the name.
6096         */
6097        function getInternalName(node: Declaration, allowComments?: boolean, allowSourceMaps?: boolean) {
6098            return getName(node, allowComments, allowSourceMaps, EmitFlags.LocalName | EmitFlags.InternalName);
6099        }
6100
6101        /**
6102         * Gets the local name of a declaration. This is primarily used for declarations that can be
6103         * referred to by name in the declaration's immediate scope (classes, enums, namespaces). A
6104         * local name will *never* be prefixed with an module or namespace export modifier like
6105         * "exports." when emitted as an expression.
6106         *
6107         * @param node The declaration.
6108         * @param allowComments A value indicating whether comments may be emitted for the name.
6109         * @param allowSourceMaps A value indicating whether source maps may be emitted for the name.
6110         */
6111        function getLocalName(node: Declaration, allowComments?: boolean, allowSourceMaps?: boolean) {
6112            return getName(node, allowComments, allowSourceMaps, EmitFlags.LocalName);
6113        }
6114
6115        /**
6116         * Gets the export name of a declaration. This is primarily used for declarations that can be
6117         * referred to by name in the declaration's immediate scope (classes, enums, namespaces). An
6118         * export name will *always* be prefixed with an module or namespace export modifier like
6119         * `"exports."` when emitted as an expression if the name points to an exported symbol.
6120         *
6121         * @param node The declaration.
6122         * @param allowComments A value indicating whether comments may be emitted for the name.
6123         * @param allowSourceMaps A value indicating whether source maps may be emitted for the name.
6124         */
6125        function getExportName(node: Declaration, allowComments?: boolean, allowSourceMaps?: boolean): Identifier {
6126            return getName(node, allowComments, allowSourceMaps, EmitFlags.ExportName);
6127        }
6128
6129        /**
6130         * Gets the name of a declaration for use in declarations.
6131         *
6132         * @param node The declaration.
6133         * @param allowComments A value indicating whether comments may be emitted for the name.
6134         * @param allowSourceMaps A value indicating whether source maps may be emitted for the name.
6135         */
6136        function getDeclarationName(node: Declaration | undefined, allowComments?: boolean, allowSourceMaps?: boolean) {
6137            return getName(node, allowComments, allowSourceMaps);
6138        }
6139
6140        /**
6141         * Gets a namespace-qualified name for use in expressions.
6142         *
6143         * @param ns The namespace identifier.
6144         * @param name The name.
6145         * @param allowComments A value indicating whether comments may be emitted for the name.
6146         * @param allowSourceMaps A value indicating whether source maps may be emitted for the name.
6147         */
6148        function getNamespaceMemberName(ns: Identifier, name: Identifier, allowComments?: boolean, allowSourceMaps?: boolean): PropertyAccessExpression {
6149            const qualifiedName = createPropertyAccessExpression(ns, nodeIsSynthesized(name) ? name : cloneNode(name));
6150            setTextRange(qualifiedName, name);
6151            let emitFlags: EmitFlags = 0;
6152            if (!allowSourceMaps) emitFlags |= EmitFlags.NoSourceMap;
6153            if (!allowComments) emitFlags |= EmitFlags.NoComments;
6154            if (emitFlags) setEmitFlags(qualifiedName, emitFlags);
6155            return qualifiedName;
6156        }
6157
6158        /**
6159         * Gets the exported name of a declaration for use in expressions.
6160         *
6161         * An exported name will *always* be prefixed with an module or namespace export modifier like
6162         * "exports." if the name points to an exported symbol.
6163         *
6164         * @param ns The namespace identifier.
6165         * @param node The declaration.
6166         * @param allowComments A value indicating whether comments may be emitted for the name.
6167         * @param allowSourceMaps A value indicating whether source maps may be emitted for the name.
6168         */
6169        function getExternalModuleOrNamespaceExportName(ns: Identifier | undefined, node: Declaration, allowComments?: boolean, allowSourceMaps?: boolean): Identifier | PropertyAccessExpression {
6170            if (ns && hasSyntacticModifier(node, ModifierFlags.Export)) {
6171                return getNamespaceMemberName(ns, getName(node), allowComments, allowSourceMaps);
6172            }
6173            return getExportName(node, allowComments, allowSourceMaps);
6174        }
6175
6176        /**
6177         * Copies any necessary standard and custom prologue-directives into target array.
6178         * @param source origin statements array
6179         * @param target result statements array
6180         * @param ensureUseStrict boolean determining whether the function need to add prologue-directives
6181         * @param visitor Optional callback used to visit any custom prologue directives.
6182         */
6183        function copyPrologue(source: readonly Statement[], target: Push<Statement>, ensureUseStrict?: boolean, visitor?: (node: Node) => VisitResult<Node>): number {
6184            const offset = copyStandardPrologue(source, target, 0, ensureUseStrict);
6185            return copyCustomPrologue(source, target, offset, visitor);
6186        }
6187
6188        function isUseStrictPrologue(node: ExpressionStatement): boolean {
6189            return isStringLiteral(node.expression) && node.expression.text === "use strict";
6190        }
6191
6192        function createUseStrictPrologue() {
6193            return startOnNewLine(createExpressionStatement(createStringLiteral("use strict"))) as PrologueDirective;
6194        }
6195
6196        /**
6197         * Copies only the standard (string-expression) prologue-directives into the target statement-array.
6198         * @param source origin statements array
6199         * @param target result statements array
6200         * @param statementOffset The offset at which to begin the copy.
6201         * @param ensureUseStrict boolean determining whether the function need to add prologue-directives
6202         * @returns Count of how many directive statements were copied.
6203         */
6204        function copyStandardPrologue(source: readonly Statement[], target: Push<Statement>, statementOffset = 0, ensureUseStrict?: boolean): number {
6205            Debug.assert(target.length === 0, "Prologue directives should be at the first statement in the target statements array");
6206            let foundUseStrict = false;
6207            const numStatements = source.length;
6208            while (statementOffset < numStatements) {
6209                const statement = source[statementOffset];
6210                if (isPrologueDirective(statement)) {
6211                    if (isUseStrictPrologue(statement)) {
6212                        foundUseStrict = true;
6213                    }
6214                    target.push(statement);
6215                }
6216                else {
6217                    break;
6218                }
6219                statementOffset++;
6220            }
6221            if (ensureUseStrict && !foundUseStrict) {
6222                target.push(createUseStrictPrologue());
6223            }
6224            return statementOffset;
6225        }
6226
6227        /**
6228         * Copies only the custom prologue-directives into target statement-array.
6229         * @param source origin statements array
6230         * @param target result statements array
6231         * @param statementOffset The offset at which to begin the copy.
6232         * @param visitor Optional callback used to visit any custom prologue directives.
6233         */
6234        function copyCustomPrologue(source: readonly Statement[], target: Push<Statement>, statementOffset: number, visitor?: (node: Node) => VisitResult<Node>, filter?: (node: Node) => boolean): number;
6235        function copyCustomPrologue(source: readonly Statement[], target: Push<Statement>, statementOffset: number | undefined, visitor?: (node: Node) => VisitResult<Node>, filter?: (node: Node) => boolean): number | undefined;
6236        function copyCustomPrologue(source: readonly Statement[], target: Push<Statement>, statementOffset: number | undefined, visitor?: (node: Node) => VisitResult<Node>, filter: (node: Node) => boolean = returnTrue): number | undefined {
6237            const numStatements = source.length;
6238            while (statementOffset !== undefined && statementOffset < numStatements) {
6239                const statement = source[statementOffset];
6240                if (getEmitFlags(statement) & EmitFlags.CustomPrologue && filter(statement)) {
6241                    append(target, visitor ? visitNode(statement, visitor, isStatement) : statement);
6242                }
6243                else {
6244                    break;
6245                }
6246                statementOffset++;
6247            }
6248            return statementOffset;
6249        }
6250
6251        /**
6252         * Ensures "use strict" directive is added
6253         *
6254         * @param statements An array of statements
6255         */
6256        function ensureUseStrict(statements: NodeArray<Statement>): NodeArray<Statement> {
6257            const foundUseStrict = findUseStrictPrologue(statements);
6258
6259            if (!foundUseStrict) {
6260                return setTextRange(createNodeArray<Statement>([createUseStrictPrologue(), ...statements]), statements);
6261            }
6262
6263            return statements;
6264        }
6265
6266        /**
6267         * Lifts a NodeArray containing only Statement nodes to a block.
6268         *
6269         * @param nodes The NodeArray.
6270         */
6271        function liftToBlock(nodes: readonly Node[]): Statement {
6272            Debug.assert(every(nodes, isStatementOrBlock), "Cannot lift nodes to a Block.");
6273            return singleOrUndefined(nodes) as Statement || createBlock(nodes as readonly Statement[]);
6274        }
6275
6276        function findSpanEnd<T>(array: readonly T[], test: (value: T) => boolean, start: number) {
6277            let i = start;
6278            while (i < array.length && test(array[i])) {
6279                i++;
6280            }
6281            return i;
6282        }
6283
6284        function mergeLexicalEnvironment(statements: NodeArray<Statement>, declarations: readonly Statement[] | undefined): NodeArray<Statement>;
6285        function mergeLexicalEnvironment(statements: Statement[], declarations: readonly Statement[] | undefined): Statement[];
6286        function mergeLexicalEnvironment(statements: Statement[] | NodeArray<Statement>, declarations: readonly Statement[] | undefined) {
6287            if (!some(declarations)) {
6288                return statements;
6289            }
6290
6291            // When we merge new lexical statements into an existing statement list, we merge them in the following manner:
6292            //
6293            // Given:
6294            //
6295            // | Left                               | Right                               |
6296            // |------------------------------------|-------------------------------------|
6297            // | [standard prologues (left)]        | [standard prologues (right)]        |
6298            // | [hoisted functions (left)]         | [hoisted functions (right)]         |
6299            // | [hoisted variables (left)]         | [hoisted variables (right)]         |
6300            // | [lexical init statements (left)]   | [lexical init statements (right)]   |
6301            // | [other statements (left)]          |                                     |
6302            //
6303            // The resulting statement list will be:
6304            //
6305            // | Result                              |
6306            // |-------------------------------------|
6307            // | [standard prologues (right)]        |
6308            // | [standard prologues (left)]         |
6309            // | [hoisted functions (right)]         |
6310            // | [hoisted functions (left)]          |
6311            // | [hoisted variables (right)]         |
6312            // | [hoisted variables (left)]          |
6313            // | [lexical init statements (right)]   |
6314            // | [lexical init statements (left)]    |
6315            // | [other statements (left)]           |
6316            //
6317            // NOTE: It is expected that new lexical init statements must be evaluated before existing lexical init statements,
6318            // as the prior transformation may depend on the evaluation of the lexical init statements to be in the correct state.
6319
6320            // find standard prologues on left in the following order: standard directives, hoisted functions, hoisted variables, other custom
6321            const leftStandardPrologueEnd = findSpanEnd(statements, isPrologueDirective, 0);
6322            const leftHoistedFunctionsEnd = findSpanEnd(statements, isHoistedFunction, leftStandardPrologueEnd);
6323            const leftHoistedVariablesEnd = findSpanEnd(statements, isHoistedVariableStatement, leftHoistedFunctionsEnd);
6324
6325            // find standard prologues on right in the following order: standard directives, hoisted functions, hoisted variables, other custom
6326            const rightStandardPrologueEnd = findSpanEnd(declarations, isPrologueDirective, 0);
6327            const rightHoistedFunctionsEnd = findSpanEnd(declarations, isHoistedFunction, rightStandardPrologueEnd);
6328            const rightHoistedVariablesEnd = findSpanEnd(declarations, isHoistedVariableStatement, rightHoistedFunctionsEnd);
6329            const rightCustomPrologueEnd = findSpanEnd(declarations, isCustomPrologue, rightHoistedVariablesEnd);
6330            Debug.assert(rightCustomPrologueEnd === declarations.length, "Expected declarations to be valid standard or custom prologues");
6331
6332            // splice prologues from the right into the left. We do this in reverse order
6333            // so that we don't need to recompute the index on the left when we insert items.
6334            const left = isNodeArray(statements) ? statements.slice() : statements;
6335
6336            // splice other custom prologues from right into left
6337            if (rightCustomPrologueEnd > rightHoistedVariablesEnd) {
6338                left.splice(leftHoistedVariablesEnd, 0, ...declarations.slice(rightHoistedVariablesEnd, rightCustomPrologueEnd));
6339            }
6340
6341            // splice hoisted variables from right into left
6342            if (rightHoistedVariablesEnd > rightHoistedFunctionsEnd) {
6343                left.splice(leftHoistedFunctionsEnd, 0, ...declarations.slice(rightHoistedFunctionsEnd, rightHoistedVariablesEnd));
6344            }
6345
6346            // splice hoisted functions from right into left
6347            if (rightHoistedFunctionsEnd > rightStandardPrologueEnd) {
6348                left.splice(leftStandardPrologueEnd, 0, ...declarations.slice(rightStandardPrologueEnd, rightHoistedFunctionsEnd));
6349            }
6350
6351            // splice standard prologues from right into left (that are not already in left)
6352            if (rightStandardPrologueEnd > 0) {
6353                if (leftStandardPrologueEnd === 0) {
6354                    left.splice(0, 0, ...declarations.slice(0, rightStandardPrologueEnd));
6355                }
6356                else {
6357                    const leftPrologues = new Map<string, boolean>();
6358                    for (let i = 0; i < leftStandardPrologueEnd; i++) {
6359                        const leftPrologue = statements[i] as PrologueDirective;
6360                        leftPrologues.set(leftPrologue.expression.text, true);
6361                    }
6362                    for (let i = rightStandardPrologueEnd - 1; i >= 0; i--) {
6363                        const rightPrologue = declarations[i] as PrologueDirective;
6364                        if (!leftPrologues.has(rightPrologue.expression.text)) {
6365                            left.unshift(rightPrologue);
6366                        }
6367                    }
6368                }
6369            }
6370
6371            if (isNodeArray(statements)) {
6372                return setTextRange(createNodeArray(left, statements.hasTrailingComma), statements);
6373            }
6374
6375            return statements;
6376        }
6377
6378        function updateModifiers<T extends HasModifiers>(node: T, modifiers: readonly Modifier[] | ModifierFlags): T;
6379        function updateModifiers(node: HasModifiers, modifiers: readonly Modifier[] | ModifierFlags) {
6380            let modifierArray;
6381            if (typeof modifiers === "number") {
6382                modifierArray = createModifiersFromModifierFlags(modifiers);
6383            }
6384            else {
6385                modifierArray = modifiers;
6386            }
6387            return isTypeParameterDeclaration(node) ? updateTypeParameterDeclaration(node, modifierArray, node.name, node.constraint, node.default) :
6388                isParameter(node) ? updateParameterDeclaration(node, modifierArray, node.dotDotDotToken, node.name, node.questionToken, node.type, node.initializer) :
6389                isConstructorTypeNode(node) ? updateConstructorTypeNode1(node, modifierArray, node.typeParameters, node.parameters, node.type) :
6390                isPropertySignature(node) ? updatePropertySignature(node, modifierArray, node.name, node.questionToken, node.type) :
6391                isPropertyDeclaration(node) ? updatePropertyDeclaration(node, modifierArray, node.name, node.questionToken ?? node.exclamationToken, node.type, node.initializer) :
6392                isMethodSignature(node) ? updateMethodSignature(node, modifierArray, node.name, node.questionToken, node.typeParameters, node.parameters, node.type) :
6393                isMethodDeclaration(node) ? updateMethodDeclaration(node, modifierArray, node.asteriskToken, node.name, node.questionToken, node.typeParameters, node.parameters, node.type, node.body) :
6394                isConstructorDeclaration(node) ? updateConstructorDeclaration(node, modifierArray, node.parameters, node.body) :
6395                isGetAccessorDeclaration(node) ? updateGetAccessorDeclaration(node, modifierArray, node.name, node.parameters, node.type, node.body) :
6396                isSetAccessorDeclaration(node) ? updateSetAccessorDeclaration(node, modifierArray, node.name, node.parameters, node.body) :
6397                isIndexSignatureDeclaration(node) ? updateIndexSignature(node, modifierArray, node.parameters, node.type) :
6398                isFunctionExpression(node) ? updateFunctionExpression(node, modifierArray, node.asteriskToken, node.name, node.typeParameters, node.parameters, node.type, node.body) :
6399                isArrowFunction(node) ? updateArrowFunction(node, modifierArray, node.typeParameters, node.parameters, node.type, node.equalsGreaterThanToken, node.body) :
6400                isClassExpression(node) ? updateClassExpression(node, modifierArray, node.name, node.typeParameters, node.heritageClauses, node.members) :
6401                isStructDeclaration(node) ? updateStructDeclaration(node, modifierArray, node.name, node.typeParameters, node.heritageClauses, node.members) :
6402                isVariableStatement(node) ? updateVariableStatement(node, modifierArray, node.declarationList) :
6403                isFunctionDeclaration(node) ? updateFunctionDeclaration(node, modifierArray, node.asteriskToken, node.name, node.typeParameters, node.parameters, node.type, node.body) :
6404                isClassDeclaration(node) ? updateClassDeclaration(node, modifierArray, node.name, node.typeParameters, node.heritageClauses, node.members) :
6405                isInterfaceDeclaration(node) ? updateInterfaceDeclaration(node, modifierArray, node.name, node.typeParameters, node.heritageClauses, node.members) :
6406                isTypeAliasDeclaration(node) ? updateTypeAliasDeclaration(node, modifierArray, node.name, node.typeParameters, node.type) :
6407                isEnumDeclaration(node) ? updateEnumDeclaration(node, modifierArray, node.name, node.members) :
6408                isModuleDeclaration(node) ? updateModuleDeclaration(node, modifierArray, node.name, node.body) :
6409                isImportEqualsDeclaration(node) ? updateImportEqualsDeclaration(node, modifierArray, node.isTypeOnly, node.name, node.moduleReference) :
6410                isImportDeclaration(node) ? updateImportDeclaration(node, modifierArray, node.importClause, node.moduleSpecifier, node.assertClause) :
6411                isExportAssignment(node) ? updateExportAssignment(node, modifierArray, node.expression) :
6412                isExportDeclaration(node) ? updateExportDeclaration(node, modifierArray, node.isTypeOnly, node.exportClause, node.moduleSpecifier, node.assertClause) :
6413                Debug.assertNever(node);
6414        }
6415
6416        function asNodeArray<T extends Node>(array: readonly T[]): NodeArray<T>;
6417        function asNodeArray<T extends Node>(array: readonly T[] | undefined): NodeArray<T> | undefined;
6418        function asNodeArray<T extends Node>(array: readonly T[] | undefined): NodeArray<T> | undefined {
6419            return array ? createNodeArray(array) : undefined;
6420        }
6421
6422        function asName<T extends DeclarationName | Identifier | BindingName | PropertyName | NoSubstitutionTemplateLiteral | EntityName | ThisTypeNode | undefined>(name: string | T): T | Identifier {
6423            return typeof name === "string" ? createIdentifier(name) :
6424                name;
6425        }
6426
6427        function asExpression<T extends Expression | undefined>(value: string | number | boolean | T): T | StringLiteral | NumericLiteral | BooleanLiteral {
6428            return typeof value === "string" ? createStringLiteral(value) :
6429                typeof value === "number" ? createNumericLiteral(value) :
6430                typeof value === "boolean" ? value ? createTrue() : createFalse() :
6431                value;
6432        }
6433
6434        function asToken<TKind extends SyntaxKind>(value: TKind | Token<TKind>): Token<TKind> {
6435            return typeof value === "number" ? createToken(value) : value;
6436        }
6437
6438        function asEmbeddedStatement<T extends Node>(statement: T): T | EmptyStatement;
6439        function asEmbeddedStatement<T extends Node>(statement: T | undefined): T | EmptyStatement | undefined;
6440        function asEmbeddedStatement<T extends Node>(statement: T | undefined): T | EmptyStatement | undefined {
6441            return statement && isNotEmittedStatement(statement) ? setTextRange(setOriginalNode(createEmptyStatement(), statement), statement) : statement;
6442        }
6443    }
6444
6445    function updateWithoutOriginal<T extends Node>(updated: Mutable<T>, original: T): T {
6446        if (updated !== original) {
6447            setTextRange(updated, original);
6448        }
6449        return updated;
6450    }
6451
6452    function updateWithOriginal<T extends Node>(updated: Mutable<T>, original: T): T {
6453        if (updated !== original) {
6454            setOriginalNode(updated, original);
6455            setTextRange(updated, original);
6456        }
6457        return updated;
6458    }
6459
6460    function getDefaultTagNameForKind(kind: JSDocTag["kind"]): string {
6461        switch (kind) {
6462            case SyntaxKind.JSDocTypeTag: return "type";
6463            case SyntaxKind.JSDocReturnTag: return "returns";
6464            case SyntaxKind.JSDocThisTag: return "this";
6465            case SyntaxKind.JSDocEnumTag: return "enum";
6466            case SyntaxKind.JSDocAuthorTag: return "author";
6467            case SyntaxKind.JSDocClassTag: return "class";
6468            case SyntaxKind.JSDocPublicTag: return "public";
6469            case SyntaxKind.JSDocPrivateTag: return "private";
6470            case SyntaxKind.JSDocProtectedTag: return "protected";
6471            case SyntaxKind.JSDocReadonlyTag: return "readonly";
6472            case SyntaxKind.JSDocOverrideTag: return "override";
6473            case SyntaxKind.JSDocTemplateTag: return "template";
6474            case SyntaxKind.JSDocTypedefTag: return "typedef";
6475            case SyntaxKind.JSDocParameterTag: return "param";
6476            case SyntaxKind.JSDocPropertyTag: return "prop";
6477            case SyntaxKind.JSDocCallbackTag: return "callback";
6478            case SyntaxKind.JSDocAugmentsTag: return "augments";
6479            case SyntaxKind.JSDocImplementsTag: return "implements";
6480            default:
6481                return Debug.fail(`Unsupported kind: ${Debug.formatSyntaxKind(kind)}`);
6482        }
6483    }
6484
6485    let rawTextScanner: Scanner | undefined;
6486    const invalidValueSentinel: object = { };
6487
6488    function getCookedText(kind: TemplateLiteralToken["kind"], rawText: string) {
6489        if (!rawTextScanner) {
6490            rawTextScanner = createScanner(ScriptTarget.Latest, /*skipTrivia*/ false, LanguageVariant.Standard);
6491        }
6492        switch (kind) {
6493            case SyntaxKind.NoSubstitutionTemplateLiteral:
6494                rawTextScanner.setText("`" + rawText + "`");
6495                break;
6496            case SyntaxKind.TemplateHead:
6497                rawTextScanner.setText("`" + rawText + "${");
6498                break;
6499            case SyntaxKind.TemplateMiddle:
6500                rawTextScanner.setText("}" + rawText + "${");
6501                break;
6502            case SyntaxKind.TemplateTail:
6503                rawTextScanner.setText("}" + rawText + "`");
6504                break;
6505        }
6506
6507        let token = rawTextScanner.scan();
6508        if (token === SyntaxKind.CloseBraceToken) {
6509            token = rawTextScanner.reScanTemplateToken(/*isTaggedTemplate*/ false);
6510        }
6511
6512        if (rawTextScanner.isUnterminated()) {
6513            rawTextScanner.setText(undefined);
6514            return invalidValueSentinel;
6515        }
6516
6517        let tokenValue: string | undefined;
6518        switch (token) {
6519            case SyntaxKind.NoSubstitutionTemplateLiteral:
6520            case SyntaxKind.TemplateHead:
6521            case SyntaxKind.TemplateMiddle:
6522            case SyntaxKind.TemplateTail:
6523                tokenValue = rawTextScanner.getTokenValue();
6524                break;
6525        }
6526
6527        if (tokenValue === undefined || rawTextScanner.scan() !== SyntaxKind.EndOfFileToken) {
6528            rawTextScanner.setText(undefined);
6529            return invalidValueSentinel;
6530        }
6531
6532        rawTextScanner.setText(undefined);
6533        return tokenValue;
6534    }
6535
6536    function propagateIdentifierNameFlags(node: Identifier) {
6537        // An IdentifierName is allowed to be `await`
6538        return propagateChildFlags(node) & ~TransformFlags.ContainsPossibleTopLevelAwait;
6539    }
6540
6541    function propagatePropertyNameFlagsOfChild(node: PropertyName, transformFlags: TransformFlags) {
6542        return transformFlags | (node.transformFlags & TransformFlags.PropertyNamePropagatingFlags);
6543    }
6544
6545    function propagateChildFlags(child: Node | undefined): TransformFlags {
6546        if (!child) return TransformFlags.None;
6547        const childFlags = child.transformFlags & ~getTransformFlagsSubtreeExclusions(child.kind);
6548        return isNamedDeclaration(child) && isPropertyName(child.name) ? propagatePropertyNameFlagsOfChild(child.name, childFlags) : childFlags;
6549    }
6550
6551    function propagateChildrenFlags(children: NodeArray<Node> | undefined): TransformFlags {
6552        return children ? children.transformFlags : TransformFlags.None;
6553    }
6554
6555    function aggregateChildrenFlags(children: MutableNodeArray<Node>) {
6556        let subtreeFlags = TransformFlags.None;
6557        for (const child of children) {
6558            subtreeFlags |= propagateChildFlags(child);
6559        }
6560        children.transformFlags = subtreeFlags;
6561    }
6562
6563    /**
6564     * Gets the transform flags to exclude when unioning the transform flags of a subtree.
6565     */
6566    /* @internal */
6567    export function getTransformFlagsSubtreeExclusions(kind: SyntaxKind) {
6568        if (kind >= SyntaxKind.FirstTypeNode && kind <= SyntaxKind.LastTypeNode) {
6569            return TransformFlags.TypeExcludes;
6570        }
6571
6572        switch (kind) {
6573            case SyntaxKind.CallExpression:
6574            case SyntaxKind.NewExpression:
6575            case SyntaxKind.ArrayLiteralExpression:
6576                return TransformFlags.ArrayLiteralOrCallOrNewExcludes;
6577            case SyntaxKind.ModuleDeclaration:
6578                return TransformFlags.ModuleExcludes;
6579            case SyntaxKind.Parameter:
6580                return TransformFlags.ParameterExcludes;
6581            case SyntaxKind.ArrowFunction:
6582                return TransformFlags.ArrowFunctionExcludes;
6583            case SyntaxKind.FunctionExpression:
6584            case SyntaxKind.FunctionDeclaration:
6585                return TransformFlags.FunctionExcludes;
6586            case SyntaxKind.VariableDeclarationList:
6587                return TransformFlags.VariableDeclarationListExcludes;
6588            case SyntaxKind.ClassDeclaration:
6589            case SyntaxKind.ClassExpression:
6590                return TransformFlags.ClassExcludes;
6591            case SyntaxKind.Constructor:
6592                return TransformFlags.ConstructorExcludes;
6593            case SyntaxKind.PropertyDeclaration:
6594                return TransformFlags.PropertyExcludes;
6595            case SyntaxKind.MethodDeclaration:
6596            case SyntaxKind.GetAccessor:
6597            case SyntaxKind.SetAccessor:
6598                return TransformFlags.MethodOrAccessorExcludes;
6599            case SyntaxKind.AnyKeyword:
6600            case SyntaxKind.NumberKeyword:
6601            case SyntaxKind.BigIntKeyword:
6602            case SyntaxKind.NeverKeyword:
6603            case SyntaxKind.StringKeyword:
6604            case SyntaxKind.ObjectKeyword:
6605            case SyntaxKind.BooleanKeyword:
6606            case SyntaxKind.SymbolKeyword:
6607            case SyntaxKind.VoidKeyword:
6608            case SyntaxKind.TypeParameter:
6609            case SyntaxKind.PropertySignature:
6610            case SyntaxKind.MethodSignature:
6611            case SyntaxKind.CallSignature:
6612            case SyntaxKind.ConstructSignature:
6613            case SyntaxKind.IndexSignature:
6614            case SyntaxKind.InterfaceDeclaration:
6615            case SyntaxKind.TypeAliasDeclaration:
6616                return TransformFlags.TypeExcludes;
6617            case SyntaxKind.ObjectLiteralExpression:
6618                return TransformFlags.ObjectLiteralExcludes;
6619            case SyntaxKind.CatchClause:
6620                return TransformFlags.CatchClauseExcludes;
6621            case SyntaxKind.ObjectBindingPattern:
6622            case SyntaxKind.ArrayBindingPattern:
6623                return TransformFlags.BindingPatternExcludes;
6624            case SyntaxKind.TypeAssertionExpression:
6625            case SyntaxKind.SatisfiesExpression:
6626            case SyntaxKind.AsExpression:
6627            case SyntaxKind.PartiallyEmittedExpression:
6628            case SyntaxKind.ParenthesizedExpression:
6629            case SyntaxKind.SuperKeyword:
6630                return TransformFlags.OuterExpressionExcludes;
6631            case SyntaxKind.PropertyAccessExpression:
6632            case SyntaxKind.ElementAccessExpression:
6633                return TransformFlags.PropertyAccessExcludes;
6634            default:
6635                return TransformFlags.NodeExcludes;
6636        }
6637    }
6638
6639    const baseFactory = createBaseNodeFactory();
6640
6641    function makeSynthetic(node: Node) {
6642        (node as Mutable<Node>).flags |= NodeFlags.Synthesized;
6643        return node;
6644    }
6645
6646    const syntheticFactory: BaseNodeFactory = {
6647        createBaseSourceFileNode: kind => makeSynthetic(baseFactory.createBaseSourceFileNode(kind)),
6648        createBaseIdentifierNode: kind => makeSynthetic(baseFactory.createBaseIdentifierNode(kind)),
6649        createBasePrivateIdentifierNode: kind => makeSynthetic(baseFactory.createBasePrivateIdentifierNode(kind)),
6650        createBaseTokenNode: kind => makeSynthetic(baseFactory.createBaseTokenNode(kind)),
6651        createBaseNode: kind => makeSynthetic(baseFactory.createBaseNode(kind)),
6652    };
6653
6654    export const factory = createNodeFactory(NodeFactoryFlags.NoIndentationOnFreshPropertyAccess, syntheticFactory);
6655
6656    export function createUnparsedSourceFile(text: string): UnparsedSource;
6657    export function createUnparsedSourceFile(inputFile: InputFiles, type: "js" | "dts", stripInternal?: boolean): UnparsedSource;
6658    export function createUnparsedSourceFile(text: string, mapPath: string | undefined, map: string | undefined): UnparsedSource;
6659    export function createUnparsedSourceFile(textOrInputFiles: string | InputFiles, mapPathOrType?: string, mapTextOrStripInternal?: string | boolean): UnparsedSource {
6660        let stripInternal: boolean | undefined;
6661        let bundleFileInfo: BundleFileInfo | undefined;
6662        let fileName: string;
6663        let text: string | undefined;
6664        let length: number | (() => number);
6665        let sourceMapPath: string | undefined;
6666        let sourceMapText: string | undefined;
6667        let getText: (() => string) | undefined;
6668        let getSourceMapText: (() => string | undefined) | undefined;
6669        let oldFileOfCurrentEmit: boolean | undefined;
6670
6671        if (!isString(textOrInputFiles)) {
6672            Debug.assert(mapPathOrType === "js" || mapPathOrType === "dts");
6673            fileName = (mapPathOrType === "js" ? textOrInputFiles.javascriptPath : textOrInputFiles.declarationPath) || "";
6674            sourceMapPath = mapPathOrType === "js" ? textOrInputFiles.javascriptMapPath : textOrInputFiles.declarationMapPath;
6675            getText = () => mapPathOrType === "js" ? textOrInputFiles.javascriptText : textOrInputFiles.declarationText;
6676            getSourceMapText = () => mapPathOrType === "js" ? textOrInputFiles.javascriptMapText : textOrInputFiles.declarationMapText;
6677            length = () => getText!().length;
6678            if (textOrInputFiles.buildInfo && textOrInputFiles.buildInfo.bundle) {
6679                Debug.assert(mapTextOrStripInternal === undefined || typeof mapTextOrStripInternal === "boolean");
6680                stripInternal = mapTextOrStripInternal;
6681                bundleFileInfo = mapPathOrType === "js" ? textOrInputFiles.buildInfo.bundle.js : textOrInputFiles.buildInfo.bundle.dts;
6682                oldFileOfCurrentEmit = textOrInputFiles.oldFileOfCurrentEmit;
6683            }
6684        }
6685        else {
6686            fileName = "";
6687            text = textOrInputFiles;
6688            length = textOrInputFiles.length;
6689            sourceMapPath = mapPathOrType;
6690            sourceMapText = mapTextOrStripInternal as string;
6691        }
6692        const node = oldFileOfCurrentEmit ?
6693            parseOldFileOfCurrentEmit(Debug.checkDefined(bundleFileInfo)) :
6694            parseUnparsedSourceFile(bundleFileInfo, stripInternal, length);
6695        node.fileName = fileName;
6696        node.sourceMapPath = sourceMapPath;
6697        node.oldFileOfCurrentEmit = oldFileOfCurrentEmit;
6698        if (getText && getSourceMapText) {
6699            Object.defineProperty(node, "text", { get: getText });
6700            Object.defineProperty(node, "sourceMapText", { get: getSourceMapText });
6701        }
6702        else {
6703            Debug.assert(!oldFileOfCurrentEmit);
6704            node.text = text ?? "";
6705            node.sourceMapText = sourceMapText;
6706        }
6707
6708        return node;
6709    }
6710
6711    function parseUnparsedSourceFile(bundleFileInfo: BundleFileInfo | undefined, stripInternal: boolean | undefined, length: number | (() => number)) {
6712        let prologues: UnparsedPrologue[] | undefined;
6713        let helpers: UnscopedEmitHelper[] | undefined;
6714        let referencedFiles: FileReference[] | undefined;
6715        let typeReferenceDirectives: FileReference[] | undefined;
6716        let libReferenceDirectives: FileReference[] | undefined;
6717        let prependChildren: UnparsedTextLike[] | undefined;
6718        let texts: UnparsedSourceText[] | undefined;
6719        let hasNoDefaultLib: boolean | undefined;
6720
6721        for (const section of bundleFileInfo ? bundleFileInfo.sections : emptyArray) {
6722            switch (section.kind) {
6723                case BundleFileSectionKind.Prologue:
6724                    prologues = append(prologues, setTextRange(factory.createUnparsedPrologue(section.data), section));
6725                    break;
6726                case BundleFileSectionKind.EmitHelpers:
6727                    helpers = append(helpers, getAllUnscopedEmitHelpers().get(section.data)!);
6728                    break;
6729                case BundleFileSectionKind.NoDefaultLib:
6730                    hasNoDefaultLib = true;
6731                    break;
6732                case BundleFileSectionKind.Reference:
6733                    referencedFiles = append(referencedFiles, { pos: -1, end: -1, fileName: section.data });
6734                    break;
6735                case BundleFileSectionKind.Type:
6736                    typeReferenceDirectives = append(typeReferenceDirectives, { pos: -1, end: -1, fileName: section.data });
6737                    break;
6738                case BundleFileSectionKind.TypeResolutionModeImport:
6739                    typeReferenceDirectives = append(typeReferenceDirectives, { pos: -1, end: -1, fileName: section.data, resolutionMode: ModuleKind.ESNext });
6740                    break;
6741                case BundleFileSectionKind.TypeResolutionModeRequire:
6742                    typeReferenceDirectives = append(typeReferenceDirectives, { pos: -1, end: -1, fileName: section.data, resolutionMode: ModuleKind.CommonJS });
6743                    break;
6744                case BundleFileSectionKind.Lib:
6745                    libReferenceDirectives = append(libReferenceDirectives, { pos: -1, end: -1, fileName: section.data });
6746                    break;
6747                case BundleFileSectionKind.Prepend:
6748                    let prependTexts: UnparsedTextLike[] | undefined;
6749                    for (const text of section.texts) {
6750                        if (!stripInternal || text.kind !== BundleFileSectionKind.Internal) {
6751                            prependTexts = append(prependTexts, setTextRange(factory.createUnparsedTextLike(text.data, text.kind === BundleFileSectionKind.Internal), text));
6752                        }
6753                    }
6754                    prependChildren = addRange(prependChildren, prependTexts);
6755                    texts = append(texts, factory.createUnparsedPrepend(section.data, prependTexts ?? emptyArray));
6756                    break;
6757                case BundleFileSectionKind.Internal:
6758                    if (stripInternal) {
6759                        if (!texts) texts = [];
6760                        break;
6761                    }
6762                    // falls through
6763
6764                case BundleFileSectionKind.Text:
6765                    texts = append(texts, setTextRange(factory.createUnparsedTextLike(section.data, section.kind === BundleFileSectionKind.Internal), section));
6766                    break;
6767                default:
6768                    Debug.assertNever(section);
6769            }
6770        }
6771
6772        if (!texts) {
6773            const textNode = factory.createUnparsedTextLike(/*data*/ undefined, /*internal*/ false);
6774            setTextRangePosWidth(textNode, 0, typeof length === "function" ? length() : length);
6775            texts = [textNode];
6776        }
6777
6778        const node = parseNodeFactory.createUnparsedSource(prologues ?? emptyArray, /*syntheticReferences*/ undefined, texts);
6779        setEachParent(prologues, node);
6780        setEachParent(texts, node);
6781        setEachParent(prependChildren, node);
6782        node.hasNoDefaultLib = hasNoDefaultLib;
6783        node.helpers = helpers;
6784        node.referencedFiles = referencedFiles || emptyArray;
6785        node.typeReferenceDirectives = typeReferenceDirectives;
6786        node.libReferenceDirectives = libReferenceDirectives || emptyArray;
6787        return node;
6788    }
6789
6790    function parseOldFileOfCurrentEmit(bundleFileInfo: BundleFileInfo) {
6791        let texts: UnparsedTextLike[] | undefined;
6792        let syntheticReferences: UnparsedSyntheticReference[] | undefined;
6793        for (const section of bundleFileInfo.sections) {
6794            switch (section.kind) {
6795                case BundleFileSectionKind.Internal:
6796                case BundleFileSectionKind.Text:
6797                    texts = append(texts, setTextRange(factory.createUnparsedTextLike(section.data, section.kind === BundleFileSectionKind.Internal), section));
6798                    break;
6799
6800                case BundleFileSectionKind.NoDefaultLib:
6801                case BundleFileSectionKind.Reference:
6802                case BundleFileSectionKind.Type:
6803                case BundleFileSectionKind.TypeResolutionModeImport:
6804                case BundleFileSectionKind.TypeResolutionModeRequire:
6805                case BundleFileSectionKind.Lib:
6806                    syntheticReferences = append(syntheticReferences, setTextRange(factory.createUnparsedSyntheticReference(section), section));
6807                    break;
6808
6809                // Ignore
6810                case BundleFileSectionKind.Prologue:
6811                case BundleFileSectionKind.EmitHelpers:
6812                case BundleFileSectionKind.Prepend:
6813                    break;
6814
6815                default:
6816                    Debug.assertNever(section);
6817            }
6818        }
6819
6820        const node = factory.createUnparsedSource(emptyArray, syntheticReferences, texts ?? emptyArray);
6821        setEachParent(syntheticReferences, node);
6822        setEachParent(texts, node);
6823        node.helpers = map(bundleFileInfo.sources && bundleFileInfo.sources.helpers, name => getAllUnscopedEmitHelpers().get(name)!);
6824        return node;
6825    }
6826
6827    // TODO(rbuckton): Move part of this to factory
6828    export function createInputFiles(
6829        javascriptText: string,
6830        declarationText: string
6831    ): InputFiles;
6832    export function createInputFiles(
6833        readFileText: (path: string) => string | undefined,
6834        javascriptPath: string,
6835        javascriptMapPath: string | undefined,
6836        declarationPath: string,
6837        declarationMapPath: string | undefined,
6838        buildInfoPath: string | undefined
6839    ): InputFiles;
6840    export function createInputFiles(
6841        javascriptText: string,
6842        declarationText: string,
6843        javascriptMapPath: string | undefined,
6844        javascriptMapText: string | undefined,
6845        declarationMapPath: string | undefined,
6846        declarationMapText: string | undefined
6847    ): InputFiles;
6848    /*@internal*/
6849    export function createInputFiles(
6850        javascriptText: string,
6851        declarationText: string,
6852        javascriptMapPath: string | undefined,
6853        javascriptMapText: string | undefined,
6854        declarationMapPath: string | undefined,
6855        declarationMapText: string | undefined,
6856        javascriptPath: string | undefined,
6857        declarationPath: string | undefined,
6858        buildInfoPath?: string | undefined,
6859        buildInfo?: BuildInfo,
6860        oldFileOfCurrentEmit?: boolean
6861    ): InputFiles;
6862    export function createInputFiles(
6863        javascriptTextOrReadFileText: string | ((path: string) => string | undefined),
6864        declarationTextOrJavascriptPath: string,
6865        javascriptMapPath?: string,
6866        javascriptMapTextOrDeclarationPath?: string,
6867        declarationMapPath?: string,
6868        declarationMapTextOrBuildInfoPath?: string,
6869        javascriptPath?: string | undefined,
6870        declarationPath?: string | undefined,
6871        buildInfoPath?: string | undefined,
6872        buildInfo?: BuildInfo,
6873        oldFileOfCurrentEmit?: boolean
6874    ): InputFiles {
6875        const node = parseNodeFactory.createInputFiles();
6876        if (!isString(javascriptTextOrReadFileText)) {
6877            const cache = new Map<string, string | false>();
6878            const textGetter = (path: string | undefined) => {
6879                if (path === undefined) return undefined;
6880                let value = cache.get(path);
6881                if (value === undefined) {
6882                    value = javascriptTextOrReadFileText(path);
6883                    cache.set(path, value !== undefined ? value : false);
6884                }
6885                return value !== false ? value as string : undefined;
6886            };
6887            const definedTextGetter = (path: string) => {
6888                const result = textGetter(path);
6889                return result !== undefined ? result : `/* Input file ${path} was missing */\r\n`;
6890            };
6891            let buildInfo: BuildInfo | false;
6892            const getAndCacheBuildInfo = (getText: () => string | undefined) => {
6893                if (buildInfo === undefined) {
6894                    const result = getText();
6895                    buildInfo = result !== undefined ? getBuildInfo(node.buildInfoPath!, result) ?? false : false;
6896                }
6897                return buildInfo || undefined;
6898            };
6899            node.javascriptPath = declarationTextOrJavascriptPath;
6900            node.javascriptMapPath = javascriptMapPath;
6901            node.declarationPath = Debug.checkDefined(javascriptMapTextOrDeclarationPath);
6902            node.declarationMapPath = declarationMapPath;
6903            node.buildInfoPath = declarationMapTextOrBuildInfoPath;
6904            Object.defineProperties(node, {
6905                javascriptText: { get() { return definedTextGetter(declarationTextOrJavascriptPath); } },
6906                javascriptMapText: { get() { return textGetter(javascriptMapPath); } }, // TODO:: if there is inline sourceMap in jsFile, use that
6907                declarationText: { get() { return definedTextGetter(Debug.checkDefined(javascriptMapTextOrDeclarationPath)); } },
6908                declarationMapText: { get() { return textGetter(declarationMapPath); } }, // TODO:: if there is inline sourceMap in dtsFile, use that
6909                buildInfo: { get() { return getAndCacheBuildInfo(() => textGetter(declarationMapTextOrBuildInfoPath)); } }
6910            });
6911        }
6912        else {
6913            node.javascriptText = javascriptTextOrReadFileText;
6914            node.javascriptMapPath = javascriptMapPath;
6915            node.javascriptMapText = javascriptMapTextOrDeclarationPath;
6916            node.declarationText = declarationTextOrJavascriptPath;
6917            node.declarationMapPath = declarationMapPath;
6918            node.declarationMapText = declarationMapTextOrBuildInfoPath;
6919            node.javascriptPath = javascriptPath;
6920            node.declarationPath = declarationPath;
6921            node.buildInfoPath = buildInfoPath;
6922            node.buildInfo = buildInfo;
6923            node.oldFileOfCurrentEmit = oldFileOfCurrentEmit;
6924        }
6925        return node;
6926    }
6927
6928    let SourceMapSource: new (fileName: string, text: string, skipTrivia?: (pos: number) => number) => SourceMapSource;
6929
6930    /**
6931     * Create an external source map source file reference
6932     */
6933    export function createSourceMapSource(fileName: string, text: string, skipTrivia?: (pos: number) => number): SourceMapSource {
6934        return new (SourceMapSource || (SourceMapSource = objectAllocator.getSourceMapSourceConstructor()))(fileName, text, skipTrivia);
6935    }
6936
6937    // Utilities
6938
6939    export function setOriginalNode<T extends Node>(node: T, original: Node | undefined): T {
6940        node.original = original;
6941        if (original) {
6942            const emitNode = original.emitNode;
6943            if (emitNode) node.emitNode = mergeEmitNode(emitNode, node.emitNode);
6944        }
6945        return node;
6946    }
6947
6948    function mergeEmitNode(sourceEmitNode: EmitNode, destEmitNode: EmitNode | undefined) {
6949        const {
6950            flags,
6951            leadingComments,
6952            trailingComments,
6953            commentRange,
6954            sourceMapRange,
6955            tokenSourceMapRanges,
6956            constantValue,
6957            helpers,
6958            startsOnNewLine,
6959            snippetElement,
6960        } = sourceEmitNode;
6961        if (!destEmitNode) destEmitNode = {} as EmitNode;
6962        // We are using `.slice()` here in case `destEmitNode.leadingComments` is pushed to later.
6963        if (leadingComments) destEmitNode.leadingComments = addRange(leadingComments.slice(), destEmitNode.leadingComments);
6964        if (trailingComments) destEmitNode.trailingComments = addRange(trailingComments.slice(), destEmitNode.trailingComments);
6965        if (flags) destEmitNode.flags = flags & ~EmitFlags.Immutable;
6966        if (commentRange) destEmitNode.commentRange = commentRange;
6967        if (sourceMapRange) destEmitNode.sourceMapRange = sourceMapRange;
6968        if (tokenSourceMapRanges) destEmitNode.tokenSourceMapRanges = mergeTokenSourceMapRanges(tokenSourceMapRanges, destEmitNode.tokenSourceMapRanges!);
6969        if (constantValue !== undefined) destEmitNode.constantValue = constantValue;
6970        if (helpers) {
6971            for (const helper of helpers) {
6972                destEmitNode.helpers = appendIfUnique(destEmitNode.helpers, helper);
6973            }
6974        }
6975        if (startsOnNewLine !== undefined) destEmitNode.startsOnNewLine = startsOnNewLine;
6976        if (snippetElement !== undefined) destEmitNode.snippetElement = snippetElement;
6977        return destEmitNode;
6978    }
6979
6980    function mergeTokenSourceMapRanges(sourceRanges: (TextRange | undefined)[], destRanges: (TextRange | undefined)[]) {
6981        if (!destRanges) destRanges = [];
6982        for (const key in sourceRanges) {
6983            destRanges[key] = sourceRanges[key];
6984        }
6985        return destRanges;
6986    }
6987}
6988