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