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